您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python-@property装饰器如何工作?

Python-@property装饰器如何工作?

property()函数返回一个特殊的描述符对象:

>>> property()
<property object at 0x10ff07940>

正是这种对象有额外的方法

>>> property().getter
<built-in method getter of property object at 0x10ff07998>
>>> property().setter
<built-in method setter of property object at 0x10ff07940>
>>> property().deleter
<built-in method deleter of property object at 0x10ff07998>

这些充当装饰过。他们返回一个新的属性对象:

>>> property().getter(None)
<property object at 0x10ff079f0>

那是旧对象的副本,但是替换了其中一个功能

记住,@decorator语法只是语法糖。语法:

@property
def foo(self): return self._foo

确实与

def foo(self): return self._foo
foo = property(foo)

因此foo该函数被替换property(foo),我们在上面看到的是一个特殊的对象。然后,当你使用时@foo.setter(),你正在做的事情就是调用property().setter我上面显示方法,该方法将返回该属性的新副本,但是这次将setter函数替换为装饰方法

下面的序列还通过使用那些装饰器方法创建了一个全开属性

首先,我们property仅使用getter 创建一些函数一个对象:

>>> def getter(self): print('Get!')
... 
>>> def setter(self, value): print('Set to {!r}!'.format(value))
... 
>>> def deleter(self): print('Delete!')
... 
>>> prop = property(getter)
>>> prop.fget is getter
True
>>> prop.fset is None
True
>>> prop.fdel is None
True

接下来,我们使用该.setter()方添加setter

>>> prop = prop.setter(setter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is None
True

最后,我们使用以下.deleter()方法添加删除器:

>>> prop = prop.deleter(deleter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is deleter
True

最后但并非最不重要的一点是,该property对象充当描述符对象,因此具有和.__get__(),可以.__set__()与.__delete__()实例属性获取,设置和删除方法挂钩:

>>> class Foo: pass
... 
>>> prop.__get__(Foo(), Foo)
Get!
>>> prop.__set__(Foo(), 'bar')
Set to 'bar'!
>>> prop.__delete__(Foo())
Delete!

Descriptor Howto包括以下类型的纯Python示例实现property()

class Property:
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)

    def getter(self, fget):
        return type(self)(fget, self.fset, self.fdel, self.__doc__)

    def setter(self, fset):
        return type(self)(self.fget, fset, self.fdel, self.__doc__)

    def deleter(self, fdel):
        return type(self)(self.fget, self.fset, fdel, self.__doc__)
python 2022/1/1 18:21:18 有360人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶