Python 描述符是一種建立託管屬性的方法。每當一個屬性被查詢時,就會發生一個動作。這個動作預設是get,set或delete。不過,有時候某個應用可能會有
更多的需求,需要你設計一些更複雜的動作。最好的解決方案就是編寫一個執行符合需求的動作的函數,然後指定它在屬性被存取時運行。一個具有這種功能的物件
稱為描述符。描述子是python方法,綁定方法,super,PRoperty,staticmethod和classmethod的實作基礎。
1.描述子協定
描述子descriptor就是一個表示屬性值的對象,透過實作一個或多個__get__,__set__,__delete__方法,可以將描述子與屬性存取機制掛鉤,也可以自訂這些操作。
__get__(self,instance,own):用於存取屬性,傳回屬性的值。 instance為使用描述符的實例對象,own為實例所屬的類別。當透過類別存取屬性時,instance為None。
__set__(self,instance,value):設定屬性值。
__delete__(self,instance):刪除屬性值。
2.描述子如何實作
class Descriptor(object):
def __get__(self, instance, owner):
print 'getting:%s'%self._name def __set__(self, instance, name):
print 'setting:%s'%name
self._name = name
def __delete (self, instance): name
def __delete____________f, instance): name
def __delete____________f, instance): %%):com del self._name
class Person (object):
name = Descriptor()
一個很簡單的描述符物件就產生了,現在可以對一個Person物件進行屬性name的讀取,設定與刪除:
>>> p=Person( )
>>> p.name='john'setting:john
>>> p.name
getting:john
'john'
>>> del p.name
deleting:john
>>> del p.name
deleting:john
類別綁定:如果A是個類別對象,呼叫方法:A.__dict__['attr'].__get__(None,A)super綁定:如果a是個super實例,那麼super(B,obj).m ()透過查詢obj.__class__.__mro__找到B的基類A,然後執行A.__dict__['m'].__get__(obj,obj.__class__)3.執行屬性類型檢查的描述符🎜
class TypedProperty(object):
def __init__(self,name,attr_type,default=None):
self.name='_'+name
遠default if default else attr_type()
def __get__(self,instance,own):
return getattr(instance,self.name,self.default)
raise TypeError,'Must be %s'%self.type
setattr(instance,self.name,value)
def __delete__(self,instance):
def __delete__(self,instance):
class 集ject):
name=TypedProperty('name',str)
num=TypedProperty('num',int,37)
,str設為int型,就會報錯:
>>> f.name=21
TypeError: Must be
>>> del f.name
AttributeError: Can not delete attribute
上述描述符實際上是儲存在實例上的,name透過setattr(f,_name,value)儲存在f._name上,num儲存在f._num上,這也是加底線的原因,