白名單 slots

      在〈白名單 slots〉中尚無留言

動態附加物件方法

在定義一個class之後, 除了可以在類別內定義物件變數, 也可以在外部臨時動態附加其他的物件變數, 這是動態語言的靈活性.

class Pokemon(object):
    pass
p1=Pokemon()
p1.name="皮卡丘" # 動態附加新的物件變數
print("%s" % p1.name)
p2=Pokemon()
print("p2沒有物件變數 : name")
結果:
皮卡丘
p2沒有物件變數 : name

如果物件變數可以動態附加, 那物件方法是否也可以動態附加呢, 答案是肯定的
首先定義一個方法, 此方法第一個參數一定要是self. 在動態方法中, 甚至可以動態附加物件變數. 最後使用MethodType(方法名, 物件名)取得方法後, 放入物件中. 請注意, MethodType需先import

from types import MethodType
class Pokemon(object):
    pass
p1=Pokemon()

def setLevel(self, l):#定義方法, 因為是物件方法, 所以要加self
    self.level=l#甚至可以在動態方法中附加動態物件變數
p1.setLevel=MethodType(setLevel, p1)#使用MethodType取得方法再附加到p1上
p1.setLevel(100)
print(p1.level)

p1動態附加方法後, 對於其他實例是起不了任何作用的. 如果希望其他實例也可調到此方法的話, 那就要把動態方法附加在class裏

Pokemon.setLevel=setLevel

強型語言只能靜態的寫在class中, 而Python這種動態附加給class的功能, 可以讓我們在程式碼運行時才決定要不要附加, 這是靜態語言無法實現的.

from types import MethodType
class Pokemon(object):
    pass
p1=Pokemon()

def setLevel(self, l):#定義方法, 因為是物件方法, 所以要加self
    self.level=l#甚至可以在動態方法中附加動態物件變數
p1.setLevel=MethodType(setLevel, p1)#使用MethodType取得方法再附加到p1上
p1.setLevel(100)
print(p1.level)

Pokemon.setLevel=setLevel
p2=Pokemon()
p2.setLevel(5000)
print(p2.level)

而且Python神奇的是, 在class動態附加方法之前就產生出來的實例, 一樣具有此新功能. 更厲害的是, 連帶子類別的實例都能擁有此新功能. 站在程式設計師的立場, 這機制要絕頂聰明的人才設計的出來.

class Pokemon(object): ......定義class
p1=Pokemon() ......產生實例
Pokemon.setLevel=setLevel ......class附加新功能
p1.setLevel() ......p1也會有setLevel新功能

白名單 slots

這種動態附加新功能的機制, 就好比人類出生後, 經過努力學習而得到了新的技術. 話是說的很正能量啦, 人也是會在出生後, 經過學習而得到了吃喝嫖賭的技術.

一個好好的class, 因為交了壞朋友, 那會不會變成病毒啊. 這個叫廢話, 而且是很容易滴

為了不讓class任意的長大, 只好限制它的成長. __slots__就是為此目的而生的. slots就好比是一個白名單, 只有在名單內的值, 才充許被增加

class Pokemon(object):
    __slots__=('setLevel', 'w', 'h')

在slots裏的值, 是以tuple的格式定義. 可以是方法名, 也可以是變數名.

如果附加的是方法, 那麼在方法內附加的物件變數, 也要加入slots, 否則也會被限制住.

請注意, slots只會限制類別本身, 子類別不受影響. 但如果子類別也寫 slots的話, 那白名單的內容會包含父類別的白名單

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *