python内置的描述符
python有些内置的描述符对象,PROperty、staticmethod、classmethod,python实现如下:
class. Property(object):
def __init__( self,getf,setf,delf,doc):
self.getf=getf
self.setf=setf
self.delf=delf
self.doc=doc
def __get__(self ,instance,own=None):
wenn die Instanz None ist:
return self
if self.getf ist None:
raise AttributeError
return self.getf( Instanz)
def __set __ (Selbst, Instanz, Wert):
Wenn self.setf keine:
sredTuteError
self.setf (Instanz, Wert)
def __del __ (Selbst, Instanz):
self.delf ist None:
raise AttributeError
self.delf(instance)
class StaticMethod(object):
def __init__(self,func):
self.func=func
def __get__(self,instance,own=None):
return self.func
class ClassMethod(object):
def __init__(self,func):
self.func=func
def __get__(self,instance,own=None):
if own ist None:
own=type(instance)
def callfunc(*args):
return. self.func(ow n, *args)
return callfunc
为属性值设置别名
有时候你想用一个属性名作为另一个属性名的别名,比如设置一些属性的默认值必须和其他属性的当前值一样,而且还需要独立的设置和删除.
class DefaultAlias(object):
def __init__ (self,name):
self.name=name
def __get __ (Selbst, Instanz, eigen):
Wenn die Instanz keine ist:#类属性 访问 时
return self
return getattr (Instance, self.name) .title ()
class Person(object):
def __init__(self,name,aliasname=None):
self.name=name
if aliasname is not None:
self.aliasname=aliasname
aliasname =DefaultAlias('name')
>>> p=Person('sam')
>>> p.aliasname
'Sam'
>>> p.aliasname='jack'
>>> p.aliasname
'jack'
>>> del p.aliasname
>>> p.aliasname
'Sam'
这样就为属性name设置了一个别名aliasname,或者说把aliasname的值存储在了name中。DefaultAlias并不是数据描述符,因为它没有__set__方法,而是一个non-data描述符.所以我们给一个实例属性赋值时(p.aliasname='jack'),实例会正常地记录属性,而且实例属性会覆盖掉类属性.这样aliasname属性就能单独的设置而不影响name属性了。当我们del现出来.
对于某些开发的类,如果
class OldAlias(object):
def __init__(self,name,oldname):
self.name=name
self.oldname=oldname
def _warn(self):
print 'use %r,not %r'%(self.name,self.oldname)
def __get__(self,instance,own):
self._warn()
wenn die Instanz None ist:
return self
return getattr(instance,self.name)
def __set__(self,instance,value):
self._warn()
setattr(instance,self.name,value)
def __del__(self,instance):
self._warn()
delattr(instance,self.name)
class NewClass(object):
def __init__(self,newname):
self.newname=newname
oldname=OldAlias('newname','oldname')
>>> c=NewClass('a')
>>> c.oldname
verwende 'newname', nicht 'oldname'
'a'
使用这个类的旧代码会使用类属性oldname,同时一个警告信息被打印,鼓励用户使用新属性newname.
缓存属性值
根据需求计算实例属性或类属性的值,并提供自动化的缓存.
class CachedAttribute(object):
def __init__(self,method,name=None):
self.method=method
self.name=name if name else method.__name__
def __get__(self,instance,own):
wenn die Instanz None ist:
return self
result=self.method(instance)
setattr(instance,self.name,result)
return result
class. MyObject(ob Projekt) :
def __init__(self,n):
self.n=n
@CachedAttribute
def quadrat(self):
return self.n*self.n
> >> m=MyObject(2)
>>> m.Quadrat
4
>>> m.n=5
>>> m.Quadrat
4
>>> del m.square
>>> m.square
25
在首次访问m.square后,square属性就被缓存在实例m中,当改变实例属性n时,square属性不会改变.如果需要清除缓存,del m.square即可,再次访问m.square属性square的值会被再次计算.
缓存类属性:
class. CachedClassAttribute(CachedAttribute):
def __get__ (self,instance,own):
return super(CachedClassAttribute,self).__get__(own,own)
class MyClass(object):
class_attr=24
@CachedClassAttribute
def quadrat (cls):
return. cls.class_attr*cls.class_attr
这样类的所有实例都有同样的缓存值了:
>>> ; a=MyClass()
>>> b=MyClass()
>>> a.quadratisch
>>> print a.square
576
>>> print b.square
576
>>> print MyClass.square
576
n)!