零基礎入門學習Python(24):魔法方法(4)描述符

零基礎入門學習Python(24):魔法方法(4)描述符

描述符就是將某種特殊類型的類的實例指派給另一個類的屬性。
某種特殊類型的類指:類中要實現下面三個方法中的至少一個。

1) __get__(self, instance, owner): 用於訪問屬性,返回屬性的值
2) __set__(self, instance, value): 在屬性分配操作中調用,不返回任何內容
3) __delete__(self, instance): 控制刪除操作,不返回任何內容

其中,self 指描述符類在內存中的地址,instance 指調用此描述符的類的實例對象在內存中的地址,owner 則指調用此描述符的類在內存中的地址。
之前講過的property其實就是一個描述符類;下面通過定義自己的 property 描述符類來深入理解一下。

>>> class MyProperty:                          #定義自己的property類
        def __init__(self,fget = None, fset = None, fdel = None):
            self.fget = fget
            self.fset = fset
            self.fdel = fdel
        def __get__(self, instance, owner):    #打印出__get__()的三個參數
            print('self: ', self)
            print('instance: ',instance)
            print('owner: ', owner)
            return self.fget(instance)         #返回值爲調用類的fget()函數
        def __set__(self, instance, value):
            self.fset(instance, value)
        def __delete__(self,instance):
            self.fdel(instance)

>>> class Test:
        def __init__(self):
            self._x = None                     #定義一個變量,可以通過getX()得到變量x的值
        def getX(self):
            return self._x
        def setX(self, value):
            self._x = value
        def delX(self):
            del self._x
        x = MyProperty(getX, setX, delX)

>>> test = Test()                              #定義一個Test類的實例
>>> test.x                                     #調用x可以得到各個參數
self:  <__main__.MyProperty object at 0x025A5870>
instance:  <__main__.Test object at 0x025A5BD0>
owner:  <class '__main__.Test'>
>>> test._x = 2                                #設置變量
>>> test.x                                     #通過x調用可以得到變量的值
self:  <__main__.MyProperty object at 0x025A5870>
instance:  <__main__.Test object at 0x025B7250>
owner:  <class '__main__.Test'>
2
>>> test.x = 3                                 #直接設置x可以得到和設置變量_x一樣的效果
>>> test._x
3
>>> del test._x                                #最後刪除變量;此時如果再調用x,則會出錯,因爲已經找不到_x這個屬性了

最後做個小練習:先定義一個溫度類,然後定義兩個描述符類用來描述攝氏度和華氏度兩個屬性;要求兩個屬性會自動進行轉換,即可以給攝氏度這個屬性賦值,然後打印的華氏度屬性是自動轉換後的結果。

>>> class Celsius:                            #攝氏度類的描述符
        def __init__(self, value = 26.0):     #設置缺省值
            self.value = float(value)
        def __get__(self, instance, owner):
            return self.value
        def __set__(self, instance, value):
            self.value = float(value)

>>> class Fahrenheit:                          #華氏度類的描述符
        def __get__(self, instance, owner):
            return instance.cel * 1.8 + 32
        def __set__(self, instance, value):
            instance.cel = (float(value) - 32) / 1.8

>>> class Temperature:
        cel = Celsius()                        #描述符類Celsius的實例,利用組合
        fah = Fahrenheit()

>>> temp = Temperature()
>>> temp.cel                                   #得到默認值
26.0
>>> temp.cel = 30
>>> temp.fah                                   #Fahrenheit類中__get__()函數return中的 instance.cel 即是 temp.cel
86.0                                           #得到轉換之後的華氏度的值
>>> temp.fah = 100                             #也可以給出華氏度,得到轉換之後的攝氏度的值
>>> temp.cel
37.77777777777778

零基礎入門學習Python(24):魔法方法(3)屬性訪問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章