1. 程式人生 > 其它 >Python描述符以及Property方法的實現原理

Python描述符以及Property方法的實現原理

技術標籤: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'