python 利用 descriptor 實現本身的 property

1.概念簡介

1.1 property

在 python 代碼中,property 是很是常見的一個內置函數。property 能夠爲一個 python 類的 attribute 設置 getter/setter,能夠類比之 C# 的 propertiespython

見下面的例子。框架

class A:
    def __init__(self):
        self.a = 1

    @property()
    def hello(self):
        return self.a

    @hello.setter()
    def hell(self, value):
        self.a = value

print(A().hello)
# output:
# 1
obj = A()
obj.hello = "hello world"
print(obj.hello)
# output:
# hello world

1.2 descriptor

python 中的 descriptor 指的是實現了__get____set____delete__三個方法之一的類。函數

當一個 descriptor 類的實例做爲其餘類的成員時,經過obj.attr語法訪問該實例將會調用 descriptor 實例的__get__方法。同理,__set____delete__也是類似的邏輯。設計

先看個例子。code

class DescriptorClass:
    def __get__(self, instance, owner):
        print(self)
        print(instance)
        print(owner)
        return 'some value'

class SomeClass:
    some_attr = DescriptorClass()

print(SomeClass().some_attr)

# output:
# <__main__.DescriptorClass object at 0x0000027AAE777160>
# <__main__.SomeClass object at 0x0000027AAE777198>
# <class '__main__.SomeClass'>
# some value

2. 實現

property 的邏輯在於,當實例訪問這個屬性時,調用方法。descriptor 恰好處在那個正確的位置上。ip

看代碼。ci

class PropertyDescriptor:
    def __init__(self, fn):
        self.getter = fn

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

    def __set__(self, instance, value):
        return self.setter(instance, value)

    def setter(self, func):
        self.setter = func
        return self

def my_property(func):
    return PropertyDescriptor(func)

class SimpleClass:
    @my_property
    def simple_attr(self):
        return 'a simple property'

    @simple_attr.setter
    def simple_attr(self, value):
        print('simple attr setter')

print(SimpleClass().simple_attr)
SimpleClass().simple_attr = 'something'

# output:
# a simple property
# simple attr setter

3. 總結

我的見解,謹慎參考get

descriptor 避免了重複編寫gettersetter方法,很是直覺的一種用途就是相似於SQLAlchemy這樣的 ORM 框架的的字段映射。不須要爲每個特定類型的字段在基類或元類裏編寫大量樣板代碼。it

但這種設計是侵入式的(須要修改目標類的代碼),並且很是不直觀。在合適的地方使用相信能夠有其發光發熱的空間。io

對可讀性來說,結合元類,這倆被一塊兒濫用的話對維護者而言徹底是地獄吧...

相關文章
相關標籤/搜索