Python 描述符(Descriptor) 附實例

在 Python 衆多原生特性中,描述符多是最少被自定義的特性之一,但它在底層實現的方法和屬性卻無時不刻被使用着,它優雅的實現方式體現出 Python 簡潔之美。

定義

  • 一個描述符是一個有「綁定行爲」的對象屬性(object attribute),它的訪問控制會被描述器協議方法重寫。
  • 任何定義了 __get__, __set__ 或者 __delete__ 任一方法的類稱爲描述符類,其實例對象即是一個描述符,這些方法稱爲描述符協議。
  • 當對一個實例屬性進行訪問時,Python 會按 obj.__dict__type(obj).__dict__type(obj)的父類.__dict__ 順序進行查找,若是查找到目標屬性並發現是一個描述符,Python 會調用描述符協議來改變默認的控制行爲。
  • 描述符是 @property@classmethod@staticmethodsuper 的底層實現機制。

特性

  • 同時定義了 __get____set__ 的描述符稱爲 數據描述符(data descriptor);僅定義了 __get__ 的稱爲 非數據描述符(non-data descriptor) 。二者區別在於:若是 obj.__dict__中有與描述符同名的屬性,若描述符是數據描述符,則優先調用描述符,如果非數據描述符,則優先使用 obj.__dict__ 中屬性。
  • 描述符協議必須定義在類的層次上,不然沒法被自動調用。

描述符協議

__get__(self, instance, owner)html

:param self: 描述符對象自己python

:param instance: 使用描述符的對象的實例程序員

:param owner: 使用描述符的對象擁有者編程

__set__(self, instance, value)緩存

:param value: 對描述符的賦值微信

__delete__(self, instance)併發

實例

class LazyProperty(object):
    """ 實現惰性求值(訪問時才計算,並將值緩存) 利用了 obj.__dict__ 優先級高於 non-data descriptor 的特性 第一次調用 __get__ 以同名屬性存於實例字典中,以後就再也不調用 __get__ """
    def __init__(self, fun):
        self.fun = fun

    def __get__(self, instance, owner):
        if instance is None:
            return self
        value = self.fun(instance)
        setattr(instance, self.fun.__name__, value)
        return value


class ReadonlyNumber(object):
    """ 實現只讀屬性(實例屬性初始化後沒法被修改) 利用了 data descriptor 優先級高於 obj.__dict__ 的特性 當試圖對屬性賦值時,總會先調用 __set__ 方法從而拋出異常 """
    def __init__(self, value):
        self.value = value

    def __get__(self, instance, owner):
        return self.value

    def __set__(self, instance, value):
        raise AttributeError(
            "'%s' is not modifiable" % self.value
         )


class Circle(object):

    pi = ReadonlyNumber(3.14)

    def __init__(self, radius):
        self.radius = radius

 @LazyProperty
    def area(self):
        print('Computing area')
        return self.pi * self.radius ** 2
複製代碼

參考文章

pyzh.readthedocs.io/en/latest/D…
ide


歡迎關注


微信公衆號:面向人生編程ui

編程思惟不該只存留在代碼之中,更應伴隨於整我的生旅途,這個公衆號不僅聊技術,還會聊產品/互聯網/經濟學等普遍話題,因此也歡迎非程序員關注。spa

相關文章
相關標籤/搜索