Day6面向?qū)ο蟾呒壘幊?/3

使用slots

正常情況下豆混,當我們定義了一個class辣吃,創(chuàng)建了一個class的實例后,我們可以給該實例綁定任何屬性和方法蒿叠,這就是動態(tài)語言的靈活性。

class Student(object):
    pass

還可以嘗試給實例綁定一個方法:

>>> def set_age(self, age): # 定義一個函數(shù)作為實例方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 給實例綁定一個方法
>>> s.set_age(25) # 調(diào)用實例方法
>>> s.age # 測試結(jié)果
25

但是蚣常,給一個實例綁定的方法市咽,對另一個實例是不起作用的:

>>> s2 = Student() # 創(chuàng)建新的實例
>>> s2.set_age(25) # 嘗試調(diào)用方法
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'set_age'

為了給所有實例都綁定方法,可以給class綁定方法:

>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = set_score

給class綁定方法后抵蚊,所有實例均可調(diào)用:

>>> s.set_score(100)
>>> s.score
100
>>> s2.set_score(99)
>>> s2.score
99

通常情況下施绎,上面的set_score方法可以直接定義在class中,但動態(tài)綁定允許我們在程序運行的過程中動態(tài)給class加上功能贞绳,這在靜態(tài)語言中很難實現(xiàn)谷醉。
但是,如果我們想要限制實例的屬性怎么辦冈闭?比如俱尼,只允許對Student實例添加nameage屬性。
為了達到限制的目的萎攒,Python允許在定義class的時候遇八,定義一個特殊的__slots__變量,來限制該class實例能添加的屬性:

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱
>>> s = Student() # 創(chuàng)建新的實例
>>> s.name = 'Michael' # 綁定屬性'name'
>>> s.age = 25 # 綁定屬性'age'
>>> s.score = 99 # 綁定屬性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

由于'score'沒有被放到__slots__中耍休,所以不能綁定score屬性刃永,試圖綁定score將得到AttributeError的錯誤。
__slots__定義的屬性僅對當前類實例起作用羊精,對繼承的子類是不起作用的


使用@property

Python內(nèi)置的@property(性能)裝飾器就是負責把一個方法變成屬性調(diào)用的斯够。

class Student(object):

    @property
    def score(self):
        return self._score        # 一定要在score前面加下劃線 否則會出現(xiàn)下面情況

    @score.setter
    def score(self,value):
        if not isinstance(value,int):
            raise ValueError('score must be a integer!')
        if value < 0 or value > 100:
            raise ValueError('score must beween 0 ~ 100!')
        self._score = value
>>> s = Student()
>>> s.score = 60
Traceback (most recent call last):
  File "<pyshell#80>", line 1, in <module>
    s.score = 60
  File "C:\Python36x32bit\practice.py", line 13, in score
    self.score = value
  File "C:\Python36x32bit\practice.py", line 13, in score
    self.score = value
  File "C:\Python36x32bit\practice.py", line 13, in score
    self.score = value
  [Previous line repeated 492 more times]
  File "C:\Python36x32bit\practice.py", line 11, in score
    if value < 0 or value > 100:
RecursionError: maximum recursion depth exceeded in comparison

注釋

  1. self.是對屬性的訪問,使用它的時候編譯器會判斷_是否為空喧锦,為空的話自動實例化读规。會自動訪問getset方法。
  2. _是對實例變量的訪問裸违,我們沒有實例化它掖桦,不能使用。
  3. 對類里局部變量訪問使用_供汛,外部變量則用self.
  4. getter方法中涌穆,不要再使用self怔昨。否則會重復調(diào)用getter方法,造成死循環(huán)宿稀。

正常情況下趁舀,把一個getter方法變成屬性,只需要加上@property就可以了祝沸,此時矮烹,@property本身又創(chuàng)建了另一個裝飾器@score.setter越庇,負責把一個setter方法變成屬性賦值,于是奉狈,我們就擁有一個可控的屬性操作:

>>> s = Student()
>>> s.score = 60 # OK卤唉,實際轉(zhuǎn)化為s.set_score(60)
>>> s.score # OK,實際轉(zhuǎn)化為s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

還可以定義只讀屬性仁期,只定義getter方法桑驱,不定義sette方法就是一個只讀屬性:

class Student(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self,value):     #可讀寫屬性
        self._birth = value

    @property
    def age(self):        #只讀屬性, 因為age可以根據(jù)birth和當前時間計算出來
        return 2018 - self._birth
>>> s = Student()
>>> s.birth = 1995
>>> s.age
23
>>> s.age = 24
Traceback (most recent call last):
  File "<pyshell#90>", line 1, in <module>
    s.age = 24
AttributeError: can't set attribute
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市跛蛋,隨后出現(xiàn)的幾起案子熬的,更是在濱河造成了極大的恐慌,老刑警劉巖赊级,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件押框,死亡現(xiàn)場離奇詭異,居然都是意外死亡理逊,警方通過查閱死者的電腦和手機强戴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挡鞍,“玉大人骑歹,你說我怎么就攤上這事∧ⅲ” “怎么了道媚?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵翘县,是天一觀的道長。 經(jīng)常有香客問我锈麸,道長,這世上最難降的妖魔是什么忘伞? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任薄翅,我火速辦了婚禮,結(jié)果婚禮上氓奈,老公的妹妹穿的比我還像新娘。我一直安慰自己舀奶,他們只是感情好暑竟,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布育勺。 她就那樣靜靜地躺著但荤,像睡著了一般罗岖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上腹躁,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音潜慎,去河邊找鬼。 笑死铐炫,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的倒信。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼榜掌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了乘综?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤胞皱,失蹤者是張志新(化名)和其女友劉穎九妈,沒想到半個月后反砌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體萌朱,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年酒贬,在試婚紗的時候發(fā)現(xiàn)自己被綠了冒晰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片同衣。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡壶运,死狀恐怖浪秘,靈堂內(nèi)的尸體忽然破棺而出埠况,到底是詐尸還是另有隱情,我是刑警寧澤棵癣,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站喜命,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏壁榕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一牌里、第九天 我趴在偏房一處隱蔽的房頂上張望务甥。 院中可真熱鬧,春花似錦敞临、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽票髓。三九已至,卻和暖如春洽沟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裆操。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工踪区, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昆烁,地道東北人缎岗。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸭巴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348