通常,訪問類和實例屬性的時候,將返回所存儲的相關值,也就是直接和類(實例的)的__dict__打交道。若果要規范這些訪問和設值方式的話,
一種方法是數據描述符,另一種就是python內置的數據描述符協議函數PRoperty()。property是一種特殊的值,訪問它時會計算它的值。
特性的原型函數是property(getf=None,setf=None,delf=None,doc=None),函數的前三個參數分別對應描述符的__get__、__set__、__delete__方法。
class Foo(object): def __init__(self,name): self._name=name def getname(self): return self._name def setname(self,value): self._name=value def delname(self): del self._name name=property(getname,setname,delname)
這樣就可以對屬性進行讀取、設置和刪除了:
>>> f=Foo('hello')>>> f.name'hello'>>> f.name='world'>>> f.name'world'>>> del f.name>>> f.nameAttributeError: 'Foo' object has no attribute '_name'
python2.6新增加了一個property裝飾器,寫起來更加的優雅。
class Foo(object): def __init__(self,name): self._name=name @property def name(self): return self._name @name.setter def name(self,value): self._name=value @name.deleter def name(self): del self._name
首先使用@property裝飾器和相關方法將屬性name設置為可讀,后面的@name.setter和@name.deleter裝飾器將其他方法與name屬性上的設置和
刪除操作相關聯。實際的name值存儲在屬性_name中。實際存儲屬性的名稱無需遵循任何約定,只需要與特性名稱不同即可。
特性的使用遵循統一訪問原則。如果沒有特性,將會以簡單屬性的形式訪問屬性,而其他屬性將以方法的形式訪問。費力去了解何時添加額外的()會帶來不必要的混淆。
實際上,方法本身是作為一類特性被隱式處理的。
class Foo(object): def __init__(self,name): self.name=name def spam(self,x): print '%s.%s'%(self.name,x)
用戶創建f=Foo('hello')這樣的實例然后訪問f.spam時,不會返回原始函數對象spam,相反會得到綁定方法。綁定方法有點類似于部分計算的函數,
其中的self參數已經填入,但其他參數仍然需要在使用()調用該函數時提供。這種綁定方法是由在后臺執行的特性函數靜靜地創建的。使用@staticmethod和
@classmethod定義靜態方法和類方法時,實際上就指定了使用不同的特性函數,以不同的方式處理對這些方法的訪問。
新聞熱點
疑難解答