Python學習之動態繫結
阿新 • • 發佈:2021-08-09
動態語言的靈活性,就是當我們定義一個class,建立class的例項後,可以給該例項繫結任何屬性和方法。
動態繫結屬性
定義一個Student類
class Student(object): def __init__(self): self
給例項繫結一個屬性
# 建立一個例項 s = Student() # 動態給例項繫結屬性 s.name = "rissa" print("name:%s" % s.name)
結果
name:rissa
動態繫結方法
需要定義一個函式作為例項方法,然後使用MethodType給例項繫結方法。
from types importMethodType class Student(object): def __init__(self): self # 定義一個函式作為例項方法 def set_score(self, score): self.score = score # 建立一個例項 s = Student() # 給例項動態繫結一個方法 s.set_score = MethodType(set_score, s) s.set_score("99") print("score:%s" % s.score)
結果
score:99
但是,給一個例項繫結的方法,對另一個例項是不起作用的
# 給例項動態繫結一個方法或屬性後,對另一個例項不起作用 s2 = Student() s2.set_score("96") print("score:%s" % s2.score)
結果
為了給所有例項都繫結方法,可以給class繫結方法,給class繫結方法後,所有例項均可呼叫。
class Student(object): def __init__(self): self # 定義一個函式作為例項方法 def set_score(self, score): self.score = score # 給class繫結方法 Student.set_score = set_score# 建立例項 s = Student() s2 = Student() s.set_score("98") print("例項s:%s" % s.score) s2.set_score("96") print("例項s2:%s" % s2.score)
例項s:98
例項s2:96
使用__slots__
當給例項動態繫結屬性時,想要限制屬性,使用__slots__變數來限制新增的屬性。
class Student(object): def __init__(self): self __slots__ = ("name", "score") # 以元組的方式 # 建立一個例項 s = Student() # 動態給例項繫結屬性 s.name = "rissa" print("name:%s" % s.name) s.score = "95" print("score:%s" % s.score) s.age = 18 print("age:%s" % s.age)
結果
由於“age”沒有被放到__slots__中,所以繫結錯誤。
使用__slots__注意,__slots__定義的屬性只對當前類例項有效,對繼承的字類的例項是無用的,除非在子類中也定義__slots__。
使用@property
在繫結屬性時,我們直接把屬性暴露出去,沒辦法檢查引數,導致可以把屬性會被隨便更改。
我們可以使用setter和getter方法,在setter方法裡面限制引數。
class Student(object): def get_score(self): return self._score def set_score(self, value): if not 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 s = Student() s.set_score(100) print("score:", s.get_score())
結果
score: 100
上述是呼叫方法的形式來訪問類的變數,那麼有沒有既能檢查引數,又可以用類似屬性這樣簡單的方式來訪問類的變數呢?需要使用Python內建的裝飾器@property
負責把一個方法變成屬性呼叫。
class Student(object): @property def score(self): return self._score @score.setter def score(self, value): if not 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 s = Student() s.score = 99 # 實際上轉換成了set_score print("score:", s.score) # 實際上轉換成了get_score
結果
score: 99
@property把一個getter方法變成了屬性,然後又建立了另一個裝飾器@score.setter負責把一個setter方法變成屬性賦值