簡介
Property,屬性通路器,又稱特性,是一種讓新式類定義自動調用方法來通路或複制執行個體屬性的方式。這種功能與Java和C#語言中的屬性(‘getter’和‘setter’)很相似,能動态地計算屬性的值而不需要在通路時調用方法。
經典句法
可以通過把一個内置函數的結果指派給一個類屬性來建立一個property,如下所示:
attribute = property(fget,fset,fdel,doc)
使用時給fget傳入一個函數用于攔截屬性通路,給fset傳入一個函數用于屬性指派,給fdel傳入一個函數用于屬性删除。如果有需要的話,doc參數還可以接收該屬性的一個文檔字元串。
class Person:
def __init__(self,name):
self._name = name
def getName(self):
print('fetch...')
return self._name
def setName(self,value):
print('change...')
self._name=value
def delName(self):
print('remove...')
del self._name
name = property(getName,setName,delName,"name propety docs")
bob=Person('Bob Smith')
print(bob.name) #調用getName
bob.name='Robert Smith' #調用setName
print(bob.name)
del bob.name #調用delName
print(Person.name.__doc__) #列印文檔字元串
運作上述代碼,輸出如下
fetch...
Bob Smith
change...
fetch...
Robert Smith
remove...
name propety docs
注意:實際資料被存儲在_name中,以便不會和property搞混了。
這樣,通過屬性調用的方式(.号),會隐式地調用property參數中相應的方法。
裝飾器形式
内置函數property可以充當一個裝飾器,來定義一個函數,并在擷取一個屬性的時候自動運作該函數
class Person:
@property
def name(self):
pass
回憶一下裝飾器的的文法格式,上述代碼等價于
class Person:
def name(self):
pass
name=property(name)
我們将第一個例子中的代碼稍加改造
class Person:
def __init__(self,name):
self._name = name
@property
def name(self):
"name propety docs" #文檔字元串移到此處
print('fetch...')
return self._name
@name.setter
def name(self,value): #函數名同為name
print('change...')
self._name = value
@name.deleter
def name(self): #函數名同為name
print('remove...')
del self._name
bob=Person('Bob Smith')
print(bob.name)
bob.name='Robert Smith'
print(bob.name)
del bob.name
print(Person.name.__doc__)
運作上述代碼會得到一樣的輸出。
和property手動指派的結果相比,使用裝飾器編寫隻需要3行額外的代碼。
說明:
property對象有getter,setter和deleter方法,由于getter元件通常有建立property自身的行為來自動填充,是以可以省略。
總結
@property廣泛應用在類的定義中,可以讓調用者寫出簡短的代碼,同時保證對參數進行必要的檢查,這樣,程式運作時就減少了出錯的可能性。