Python-Deskriptor descriptor(2)

黄舟
Freigeben: 2016-12-23 17:38:57
Original
1275 Leute haben es durchsucht

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)!


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage