在繫結屬性的時候,如過我們直接把屬性暴露出去,雖然寫起來簡單,但是,沒辦法檢查引數,導致可以把成績隨意改:
s =student()s.score = 9999 #
不符合常規依然可以更改
這顯然不合邏輯。為了限制score的範圍,可以通過乙個set_score()方法來設定成績,再通過乙個get_score()來獲取成績,這樣,在set_score方法裡,就可以檢查引數:
classstudent(object):
defget_score(self):
return
self._score
defset_score(self, value):
ifnot
isinstance(value, int):
raise valueerror('
score must be an integer!')
if value < 0 or value > 100:
raise valueerror('
score must between 0 ~ 100!')
self._score = value
現在,對任意的student例項進行操作,就不能隨心所欲地設定score了:
>>> s =student()>>> s.set_score(60) #
ok!>>>s.get_score()
60>>> s.set_score(9999)
traceback (most recent call last):
...valueerror: score must between 0 ~ 100!
但是,上面地呼叫方法又略顯複雜,沒有直接用屬性這麼直接簡單。
有沒有既能檢查引數,又可以用類似屬性這樣簡單地方式來訪問類地變數了?對於追求完美地python程式設計師來說,這是必須要做到的!
還記得裝飾器可以給函式動態加上功能嗎?對於類的方法,裝飾器一樣起作用,python內建的@propert裝飾器就是負責把乙個方法變成屬性呼叫:
classstudent(object):
@property
defscore(self):
return
self._score
@score.setter
defscore(self, value):
ifnot
isinstance(value, int):
raise valueerror('
score must be an integer!')
if value < 0 or value > 100:
raise valueerror('
score must between 0 ~ 100!')
self._score = value
@property的實現比較複雜,我們先只關注如何使用。把乙個getter方法變成屬性,只需要加上@property就可以實現了,此時,@property本身又建立了另乙個裝飾器@score.setter,負責把乙個setter方法變成屬性賦值,於是我們就有了乙個可控的屬性操作:
>>> s =student()>>> s.score = 60 #
ok,實際轉化為s.set_score(60)
>>> s.score #
ok,實際轉化為s.get_score()
60>>> s.score = 9999traceback (most recent call last):
...valueerror: score must between 0 ~ 100!
注意到這個神奇的@property,我們對例項屬性操作的時候,就知道該屬性很可能不是直接暴露的,而是通過getter和setter方法實現的。
還可以定義制度屬性,只定義getter方法,不定義setter方法就是乙個唯讀屬性。
classstudent(object):
@property
defbirth(self):
return
self._birth
@birth.setter
defbirth(self, value):
self._birth =value
@property
defage(self):
return 2015 - self._birth
@property廣泛應用在類的定義中,可以讓呼叫者寫出簡短的**,同時保證對引數進行必要的檢查。
classgoods:
__discount = 0.8
def__init__
(self,name):
self.name =name
self.
__price = 100@property
#將乙個方法變成屬性
defprice(self):
return self.__price * goods.__discount
@price.setter
defprice(self,new_price):
self.
__price =new_price
@price.deleter
defprice(self):
del self.__price蘋果'
)有=就可以關聯到屬性,原本是不能訪問的,因為隱藏了
#del會關聯到deleter
#
如果沒有@property就沒有下面的setter和delete。
classfoo:
@property
def aaa(self): #
aaa已經變成了屬性
print("
get的時候執行我")
@aaa.setter
#現在我想修改或重賦值aaa的屬性,就可以關聯到這裡
defaaa(self,value):
print("
set的時候執行我")
@aaa.deleter
#我想刪除屬性的時候,出現刪除的命令的時候就會關聯到這
defaaa(self):
print("
delete的時候執行我")
f1 =foo()
f1.aaa
f1.aaa = '
aaa'
delf1.aaa
結果:get的時候執行我
set的時候執行我
delete的時候執行我
物件導向高階程式設計
相同class的各物件互為友元 class complex int func const complex param private double re,im string inline string string const char cstr 0 else inline string strin...
python 物件導向高階程式設計
python 裝飾器 property使用 classscreen property defwidth self returnself.width pass width.setter defwidth self,value self.width value property defheight se...
python物件導向高階程式設計
1.繫結方法 給所有例項都繫結方法,可以給class繫結方法 def set score self,score self.score score student.set score set score 給class繫結方法後,所有例項均可呼叫。但是,如果我們想要限制例項的屬性怎麼辦?比如,只允許對s...