要瞭解@property的用途,首先要瞭解如何創建一個屬性。 一般而言,屬性都通過__init__方法創建,比如: 創建實例,運行結果: 但是這樣子有2個壞處: 1.__init__ 中定義的屬性是可變的,如果一個系統的開發人員在知道屬性名的情況下,就可以進行隨意更改(儘管可能是在無意識的情況下), ...
要瞭解@property的用途,首先要瞭解如何創建一個屬性。
一般而言,屬性都通過__init__方法創建,比如:
1 class Student(object): 2 def __init__(self,name,score): 3 self.name=name 4 self.score=score
創建實例,運行結果:
1 tim=Student('Tim',97) 2 tim.score=100 3 tim.score 4 100 5 mary=Student('Mary',90) 6 mary.score 7 90
但是這樣子有2個壞處:
1.__init__ 中定義的屬性是可變的,如果一個系統的開發人員在知道屬性名的情況下,就可以進行隨意更改(儘管可能是在無意識的情況下),如果一不小心篡改了,後臺排查很難!
2.不利於進行參數檢查,比如:score屬性範圍本該是[0,100],但如果輸成了1000也不會報錯。
因此,一個標準的創建屬性流程如下:
1.定義三個跟屬性(本例中是score)相關的函數:
get(用於返回score屬性)
set(用於設定score屬性)
del(用於刪除score屬性)
在set函數中,可以添加一些取值範圍,比如[0,100].此外,為了私有化屬性,前面可以加上__。
這樣就做到了既能通過創建實例設定屬性,又不讓開發人員輕易修改score屬性。
如下所示:
1 class Student(object): 2 def getScore(self): 3 return self.__score 4 5 def setScore(self,score): 6 if score>100 or score<0: 7 raise ValueError ('score is out of range.') 8 else: 9 self.__score=score 10 11 def delScore(self): 12 del self.__score
這樣,一旦score取值不在設定範圍內,就會報錯!
創建一個實例,能夠正常運行:
1 Mary=Student() 2 Mary.setScore(90) 3 Mary.getScore() 4 90
但是,通過方法getScore()查看分數似乎還是有點繁瑣,能不能把它當作一個屬性去調用呢?至少調用不需要輸入()嘛!
當然是可以的。
辦法就是通過裝飾器:@property
通過給getScore,setScore,delScore三個方法分別添加三個裝飾器,就可以直接把這三個方法作為屬性去調用了!
如下所示:
1 class Student(object): 2 @property 3 def getScore(self): 4 return self.__score 5 @getScore.setter 6 def setScore(self,score): 7 if score>100 or score<0: 8 raise ValueError ('score is out of range.') 9 else: 10 self.__score=score 11 @getScore.deleter 12 def delScore(self): 13 del self.__score
1 tim=Student() 2 tim.setScore=90 3 tim.getScore 4 90
非常神奇!方法居然變成了屬性,為什麼呢?
因為裝飾器@property本質上是一個property()函數,property()函數也是一個裝飾器。
一般的裝飾器是用在普通函數上,而@property是用在類內的方法上。
property()函數包含了三個部分:getter,setter,deleter。
因為setter和deleter是property()的第二和第三個參數,不能直接套用@語法。
因此,本質上@property相當於getter部分,@setScore.setter相當於setter部分,@delScore.deleter相當於deleter部分。
所以,上面的代碼本質上等價於:
1 class Student(object): 2 def getScore(self): 3 return self.__score 4 5 def setScore(self,score): 6 if score>100 or score<0: 7 raise ValueError ('score is out of range.') 8 else: 9 self.__score=score 10 11 def delScore(self): 12 del self.__score 13 14 score=property(getScore,setScore,delScore,'description')
最後,為了函數名美觀,可以把函數名字改成Score():
1 class Student(object): 2 @property 3 def Score(self): 4 return self.__score 5 @Score.setter 6 def Score(self,score): 7 if score>100 or score<0: 8 raise ValueError ('score is out of range.') 9 else: 10 self.__score=score 11 @Score.deleter 12 def delScore(self): 13 del self.__score 14 15 tim=Student() 16 tim.Score=90 17 tim.Score 18 90
幾篇個人覺得寫的比較清楚的文章:
http://www.runoob.com/python/python-func-property.html
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186781871161bc8d6497004764b398401a401d4cce000
https://www.cnblogs.com/cicaday/p/python-decorator.html