首先,property裝飾器是經過數據描述符實現的。用法很簡單,你們應該都知道,這裏就不細說了。html
這裏主要分析一下property是如何經過描述符實現的。python
class Property: def __init__(self, fget): self.fget = fget # 爲實例增長方法,這裏的方法是未綁定實例的,不會自動傳入實例self self.fset = None # 同上,未綁定實例 def __get__(self, instance, owner): if instance is not None: return self.fget(instance) # 調用原方法,傳入實例self return self def __set__(self, instance, value): self.fset(instance, value) # 調用原方法,傳入實例self和value def setter(self, func): self.fset = func # 更新屬性 return self class A: def __init__(self, data): self._data = data @Property # data = Property(data) 描述符實例 def data(self): return self._data @data.setter # data = data.setter(data) 更新屬性,並返回描述符實例 def data(self, value): self._data = value
訪問函數
a = A(100) print(a.data) # 訪問描述符實例,調用__get__()方法 # 100 執行過程以下: 1. 在裝飾器中,data變量指向Property(func)描述符實例 2. 原data()函數被賦值給fget變量 3. a.data就是訪問描述符實例,觸發調用__get__()方法 4. 最後,調用fget()也就是原data()方法,並傳入owner class的實例,亦即調用data(self)
賦值code
a.data = 200 # 訪問描述符實例,調用__set__()方法 print(a.data) # 訪問描述符實例,調用__get__()方法 # 200 執行過程以下: 1. 在裝飾器中,data變量指向data.setter(func)描述符實例。注意,後面的data是__get__()方法返回的描述符實例 2. 原data()函數被賦值給fset變量 3. 賦值操做觸發調用__set__方法 4. 最後,調用fset也就是原data()方法,並傳入owner class的實例和要賦的值,亦即調用data(self, value)
這裏涉及到裝飾器,須要對裝飾器和麪向對象有足夠的瞭解才能弄明白當中的變量傳遞,但願你不會被擋住。htm
參考:
https://docs.python.org/3/library/functions.html#property對象