手動實現property裝飾器
阿新 • • 發佈:2019-01-05
首先,property裝飾器是通過資料描述符實現的。用法很簡單,大家應該都知道,這裡就不細說了。
這裡主要分析一下property是如何通過描述符實現的。
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)
賦值
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)
這裡涉及到裝飾器,需要對裝飾器和麵向物件有足夠的瞭解才能弄明白當中的變數傳遞,希望你不會被擋住。
參考:
https://docs.python.org/3/library/functions.html#property