Python描述符以及Property方法的實現原理
阿新 • • 發佈:2021-01-14
技術標籤:python
Python描述符以及Property方法的實現原理
描述符的定義:
描述符是什麼:描述符本質就是一個新式類,在這個新式類中,至少實了__get__(),__set__(),__delete__()中的一個,這也被稱為描述符協議
__get__():呼叫一個屬性時,觸發
__set__():為一個屬性賦值時,觸發
__delete__():採用del刪除屬性時,觸發
描述符作用:
描述符的作用是用來代理另外一個類的屬性的(必須把描述符定義成這個類的類屬性,不能定義到建構函式中)
可以說成是屬性的屬性,定義屬性的屬性
描述符本身的例項並不會觸發這三個方法
class dis:
def __set__(self, instance, value):
print('正在執行__set__方法.....')
def __delete__(self, instance):
print('正在執行__delete__方法')
def __get__(self, instance, owner):
print('正在執行__get__方法')
d = dis()
d.name = "1"
print(d.name)
del d.name
#================輸出===================
1
描述符解析
分析程式碼
class dis:
def __init__(self, fget, fset, fdel):
self.fget = fget
self.fset = fset
self.fdel = fdel
print('正在執行__init__方法.....')
def __set__(self, instance, value):
print('正在執行__set__方法.....')
print(instance, value)
def __delete__ (self, instance):
print('正在執行__delete__方法')
print(instance)
def __get__(self, instance, owner):
print('正在執行__get__方法')
print(instance, owner)
class test:
def __init__(self, value = 10):
self.value = value
def fset(self, value):
self.value = value
def fget(self):
return self.value
def fdel(self):
del self.value
x = dis(fget, fset, fdel)
t = test()
print(t.x)
t.x = 20
print(t.x)
del t.x
輸出
正在執行__init__方法.....
正在執行__get__方法
<__main__.test object at 0x0000016CA299CEE0> <class '__main__.test'>
None
正在執行__set__方法.....
<__main__.test object at 0x0000016CA299CEE0> 20
正在執行__get__方法
<__main__.test object at 0x0000016CA299CEE0> <class '__main__.test'>
None
正在執行__delete__方法
<__main__.test object at 0x0000016CA299CEE0>
當test類試圖去通過x屬性來訪問自身的value屬性時,就會自動跳轉到執行dis類裡面的__get__方法。
當試圖通過x去修改value的屬性時就會執行dis類裡面的__set__方法。
當試圖通過x去刪除value的屬性時會執行dis類裡面的__del__方法。
然後我把它們的引數型別打印出來可以知道;
instance
引數指的是test
類的例項化物件t;
owner
指的是test
類;
因為這幾個方法我只是把值給打印出來,並未給出有效操作的程式碼,就返回值一直是None
知道了上面之後我們可以實現property方法。
class dis:
def __init__(self, fget = None, fset = None, fdel = None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __set__(self, instance, value):
self.fset(instance, value)#這裡fset的引數型別看test裡面的fset就行,鴨子型別
def __delete__(self, instance):
self.fdel(instance)
def __get__(self, instance, owner):
return self.fget(instance)
以上大概就是property方法,然後再加上測試的程式碼
class test:
def __init__(self, value = 10):
self.value = value
def fset(self, value):
self.value = value
def fget(self):
return self.value
def fdel(self):
del self.value
x = dis(fget, fset, fdel)
t = test()
print(t.x)
t.x = 20
print(t.x)
del t.x
try:
print(t.x)
except AttributeError as reason:
print("出錯啦"+str(reason))
這裡是輸出結果:
10
20
出錯啦'test' object has no attribute 'value'