天天看點

關于Python中 “描述符“ 的了解

這裡引用一段代碼來試圖說明我對描述符的了解

class A():                   #定義關于攝氏度的描述符
    def __init__(self,value = 30.0):
        self.value = float(value)
        
    def __get__(self,instance,owner):  
        return self.value
    
    def __set__(self,instance,value):
        self.value = float(value)
        
class B():             #定義關于華氏度的描述符
    def __get__(self,instance,owner):  #攝氏度轉華氏度
        return instance.cel*1.8+32

    def __set__(self,instance,value):  #華氏度轉攝氏度
        instance.cel = (float(value)-32)/1.8
        
class T():                 
    cel = A()
    har = B()            #定義攝氏度屬性cel與華氏度屬性har
#運作結果如下
In[]: a = T()
In[]: a.cel

Out[]: 30.0

In[]: a.har

Out[]: 86.0

In[]: a.har = 70
In[]: a.cel

Out[]: 21.11111111111111

           

首先明确描述符的定義:

描述符就是一個具有綁定行為的對象屬性,其屬性通路将由描述符協定中的方法覆寫。這些方法為__get__、set__和__delete。如果這些方法中的任何一個針對某個對象定義,那麼它就被認為是一個描述符

__get__方法是指目前屬性的值被取得時則調用該方法

__set__方法是指目前屬性的值被修改時則調用該方法

__delete__方法是指目前屬性的值被删除時則調用該方法

參數instance表示目前執行個體化對象

參數owner表示目前執行個體化對象所屬的類

來看代碼

當使用a來執行個體化T類時,此時a内已經含有cel屬性

a=T()

a.cel = 30

因為在a執行個體化T類時,首先自動調用了 A() 類内的__init__()方法,此時已經傳值給value,使得a.cel得到value的值為30。

指令行調用a.har屬性,傳回得到86.0

In[] : a.har

Out[] : 86.0

def __get__(self,instance,owner):    #B類中__get__方法 屬性值被取得時調用
        return instance.cel*1.8+32
           

這裡是因為使用a.har時,自動調用了B類中的__get__()方法,則取得a.har的值

此處函數中的instance參數就是指目前執行個體a,傳回值即是a.cel參與運算的運算結果,即是調用a.har的結果

In[]:a.har = 70

In[]:a.cel

Out[]:21.11111111111

此處修改屬性a.har的值,再檢視a.cel屬性的值,發現随之改變

def __set__(self,instance,value):  #B類中的__set__方法 屬性值被修改時調用
        instance.cel = (float(value)-32)/1.8
           
def __get__(self,instance,owner):   #A類中的__get__方法 屬性值被取得時調用
        return self.value
           

a.har = 70這句語句觸發時,辨別執行個體化對象a的屬性har值被修改,則此時自動調用har依托的B類中的__set__方法,此時傳入函數的參數instance=執行個體化對象a,value = 70,進行将(70-32)/1.8 的結果指派給a.cel的操作。

而給a.cel指派,即調用了cel依托的A類中__set__方法并傳入參數value = (70-32)/1.8 ,使得函數内self.value = (70-32)/1.8。

再次檢視a.cel的值,則調用cel依托A類中的__get__方法傳回目前cel屬性的值,即為上指派給該屬性的(70-32)/1.8。

解釋代碼過程我使用了‘依托’這個詞來表示屬性與描述符之間的關系,實際上并不能這麼了解,但是能力有限,也隻能這樣描述了。

整個代碼過程相當于,使用a來對T類進行執行個體化時,在T類内含有屬性cel與屬性har,則執行個體化對象a含有cel與har兩屬性。通過cel = A()語句來實作cel與A類描述符的相關聯,屬性har同理。此時對兩屬性進行重寫函數的操作時,則會自動調用你重寫的相關操作的方法

第一次寫這種部落格,描述能力實在有限,大家願意看下去的我在這裡多謝了。如果了解有什麼問題也歡迎大家評論區提出來或者留言,感謝感謝