>백엔드 개발 >파이썬 튜토리얼 >파이썬 설명자 설명자(2)

파이썬 설명자 설명자(2)

黄舟
黄舟원래의
2016-12-23 17:38:571291검색

python内置的描述符

python有些内置的描述符对象,PROperty、staticmethod、classmethod,python实现如下:

class Property(object):
   def __초기화__( self,getf,setf,delf,doc):
       self.getf=getf
       self.setf=setf
       self.delf=delf
       self.doc=doc
   def __get__(self ,instance,own=None):
       인스턴스가 None인 경우:
           return self
       if  self.getf가 None인 경우:
           속성 오류 발생
       return self.getf(instance)
   데프 __set__(self,instance,value):
       self.setf가 None인 경우:
           raise AttributeError
       self.setf(instance,value)
   def __del__(self,instance):
       if self.delf는 없음:
           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):
       own이 None인 경우:
           own=type(instance)
       def callfunc(*args):
           return self.func(own, *args)
       return callfunc

为属性值设置别name

有时候你想用一个属性name 作为另一个属性性别name,比如设置一些属性默认值必须和其他属性的当前值一样,而且还需要独立的设置 and删除。

class DefaultAlias(object):
   def __init__(self,name):
    self.name=이름
   def __get__(self,instance,own):
       인스턴스가 None인 경우:  #类属性访问时
           return self
       return getattr(instance,self.name).title()
class Person(object):
   def __init__(self,name,aliasname=None):
       self.name=name
       aliasname이 None이 아닌 경우:
           self.aliasname=aliasname
   aliasname =DefaultAlias('이름')
>>> p=Person('sam')
>>> p.aliasname
'Sam'
>>> p.aliasname='jack'
>>> p.aliasname
'jack'
>>> del p.aliasname
>>> p.aliasname
'Sam'

这样就为属性name设置了一个别namealiasname,或者说把aliasname的值存储在了name中。DefaultAlias并不是数据描述符,因为它没有__set__방법, 而是一个비데이터描述符.所以我们给一个实例属性赋值时(p.aliasname='jack'),实例会正常地记录属性, 而且实例属性会覆盖掉类属性。这样aliasname属性就能单独的设置而不影响name属性了。当我们del p.aliasname时,删除了实例的属性,类属性又会再次显现来。

对于某些开发的类,如果要保持后续版本적兼容性, 可以usenewname称来命name방법과属性, 同时保留旧name字的可用性.

class OldAlias(객체):
   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()
       인스턴스가 None인 경우:  
           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
'oldname'이 아닌 'newname'을 사용하세요.
'a'

使用这个类的旧代码会使用类属性oldname,同时一个警告信息被打印,鼓励用户使用新属性newname。

缓存属性值

根据需求计算实例属性或类属性值,并提供自动化的缓存。

클래스 CachedAttribute(객체):
   def __init__(self,method,name=None):
       self.method=method
       self.name=name if name else method.__name__
   def __get__(self,instance,own):
       인스턴스가 None인 경우:
           return self
       result=self.method(instance)
       setattr(instance,self.name,result)
       결과 반환
class MyObject(object) :
   def __init__(self,n):
       self.n=n
   @CachedAttribute
   def square(self):
       return self.n*self.n
> >> m=MyObject(2)
>>> m.square
4
>>> m.n=5
>>> m.square
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 square (cls):
       cls.class_attr*cls.class_attr 반환

这样类的所有实例所有实值了:

>>> a=MyClass()
>>> b=MyClass()
>>> a.square
>>> a.square 인쇄
576
>>> b.square 인쇄
576
>>> print MyClass.square
576

 以上就是python描述符descriptor(two)的内容,更多相关容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.