網路上教學很多,而且不難懂,只是沒有我的風格。(推薦: 官方文件)
@又名Property屬性,property() 是python的內置函數。在定義 類別class 的時候,也經常設定其相關屬性。
Property由四個部分組成:getter、 setter、 deleter、 doc。
以a為例,getter、 setter、 deleter分別對應:
a # call getter a = 1 # call setter del a # call deleter發生以上三種狀況,就會分別執行對應的函式。
依照官方的範例稍微改寫,例1:
class C(object): def __init__(self): self._x = None def getx(self): print("得了") return self._x def setx(self, value): print("設了") self._x = value def delx(self): print("刪了") del self._x x = property(getx, setx, delx, "docstring") a = C() a.x # a.getx() a.x = 1 # a.setx() del a.x # a.delx()得到以下輸出。
得了 設了 刪了使用Property後可以減少代碼,除了例1的寫法,Property可以寫得更簡化。
用上「@」,更快速使用Property,簡化代碼。例1也可以寫成例2:
class C(object): def __init__(self): self._x = None @property def x(self): print("得了") return self._x @x.setter def x(self, value): print("設了") self._x = value @x.deleter def x(self): print("刪了") del self._x@property 就是將下方函式定義為 x 的 getter, 然後 x = property(getter),下方函式名 x 就會變成屬性。
看例2,@property 為 getter。 setter也可以寫成@屬性.setter 、 deleter 寫成@屬性.deleter。
getter 最常被使用也一定要設置,setter、 deleter 就不一定要設置。
知道使用 @property 可以將 a.getx() 省略成 a.x 。a.x 就等於 a.getx() 的回傳值。
舉一個實例,如果要定義一個長方形類別,可能會在 __init__() 中,設定其長與寬,然後透過長與寬計算出面積。
class Rectangle(): def __init__(self, width, height): self.width = width self.height = height self.area = width * height如果 width = 5、 height = 4,那麼 area = 20。
但是,要是後面只改變了 width 或是 height, area 並不會自動更新數值,仍是舊的 20。
如果用上 @property 設定 area,就會在呼叫 area 時,重新計算數值。
class Rectangle(): def __init__(self, width, height): self.width = width self.height = height @property def area(self): return self.width * self.height使用 @property 可將像 area 這類動態數值的過程簡化成屬性名,除了大幅減少代碼篇幅,使用上也變得更直覺,。
學到這裡,講完了property的基本運作,現在來看一下其他教學中的舉例。
如果有好好從前面讀懂,這個範例應該是很好理解,範例3:
def f1(f2): return 1 @f1 def f2(x): return 2 f2(1) # Error先不講結果,先順著 property 的邏輯看。
@f1,getter 為 f1,f2 = property(f1),下方函式名 f2 變成屬性。
於是 f2 == 「f1的回傳值」 == 1、f2 + f2 == 2。
行7嘗試 f2(1) ,就會報錯,無法理解 f2(1) 為什麼會錯, 就換成 1(1) 理解看看吧。
行1寫成 f1(f2),是方便理解整個 f2函式 都會傳入到 f1。
由於函式內外部差異,可以將傳入的 f2 跟外部的 f2 視作不同的東西。
因此呼叫傳入的 f2 並不會觸發外部帶有@的 f2。
最後範例,如果無法理解,就回過頭看上方的說明吧。範例4:
def addition(f): answer = 0 for num in f(): answer += num return answer @addition def threePlusFive(): return [3, 5] @addition def threePlusFivePlusEight(): return [3, 5, 8] @addition def threePlusFivePlusEight2(): return [threePlusFive, 8] print(threePlusFive) print(threePlusFivePlusEight) print(threePlusFivePlusEight2)