1. 程式人生 > >Python中的@property裝飾器

Python中的@property裝飾器

代碼 屬性範圍 直接 裝飾器。 ini def desc 裝飾 本質

要了解@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

Python中的@property裝飾器