@property装饰器在Python中如何工作?

我想了解内置函数的property工作原理。令我感到困惑的是,property它还可以用作装饰器,但仅在用作内置函数时才接受参数,而在用作装饰器时则不接受参数。


这个例子来自文档:


class C:

    def __init__(self):

        self._x = None


    def getx(self):

        return self._x

    def setx(self, value):

        self._x = value

    def delx(self):

        del self._x

    x = property(getx, setx, delx, "I'm the 'x' property.")

property的论点是getx,setx,delx和文档字符串。


在下面的代码中property用作装饰器。它的对象是x函数,但是在上面的代码中,参数中没有对象函数的位置。


class C:

    def __init__(self):

        self._x = None


    @property

    def x(self):

        """I'm the 'x' property."""

        return self._x


    @x.setter

    def x(self, value):

        self._x = value


    @x.deleter

    def x(self):

        del self._x

在这种情况下,x.setter和x.deleter装饰器是如何创建的?


千巷猫影
浏览 195回答 3
3回答

三国纷争

该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语法只是语法糖。语法:@propertydef foo(self): return self._foo确实与def foo(self): return self._foofoo = property(foo)因此foo该函数被替换了property(foo),我们在上面看到的是一个特殊的对象。然后,当您使用时@foo.setter(),您正在做的事情就是调用property().setter我上面显示的方法,该方法将返回该属性的新副本,但这一次是将setter函数替换为装饰方法。下面的序列还通过使用那些装饰器方法创建了一个全开属性。首先,我们创建一些函数和一个property仅带有吸气剂的对象:>>> def getter(self): print('Get!')...&nbsp;>>> def setter(self, value): print('Set to {!r}!'.format(value))...&nbsp;>>> def deleter(self): print('Delete!')...&nbsp;>>> prop = property(getter)>>> prop.fget is getterTrue>>> prop.fset is NoneTrue>>> prop.fdel is NoneTrue接下来,我们使用该.setter()方法添加一个setter:>>> prop = prop.setter(setter)>>> prop.fget is getterTrue>>> prop.fset is setterTrue>>> prop.fdel is NoneTrue最后,我们使用以下.deleter()方法添加删除器:>>> prop = prop.deleter(deleter)>>> prop.fget is getterTrue>>> prop.fset is setterTrue>>> prop.fdel is deleterTrue最后但并非最不重要的,property对象作为一个描述符对象,所以它有.__get__(),.__set__()和.__delete__()方法挂接到实例属性获取,设置和删除:>>> class Foo: pass...&nbsp;>>> prop.__get__(Foo(), Foo)Get!>>> prop.__set__(Foo(), 'bar')Set to 'bar'!>>> prop.__delete__(Foo())Delete!Descriptor Howto包括以下类型的纯Python示例实现property():class Property:&nbsp; &nbsp; "Emulate PyProperty_Type() in Objects/descrobject.c"&nbsp; &nbsp; def __init__(self, fget=None, fset=None, fdel=None, doc=None):&nbsp; &nbsp; &nbsp; &nbsp; self.fget = fget&nbsp; &nbsp; &nbsp; &nbsp; self.fset = fset&nbsp; &nbsp; &nbsp; &nbsp; self.fdel = fdel&nbsp; &nbsp; &nbsp; &nbsp; if doc is None and fget is not None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doc = fget.__doc__&nbsp; &nbsp; &nbsp; &nbsp; self.__doc__ = doc&nbsp; &nbsp; def __get__(self, obj, objtype=None):&nbsp; &nbsp; &nbsp; &nbsp; if obj is None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return self&nbsp; &nbsp; &nbsp; &nbsp; if self.fget is None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise AttributeError("unreadable attribute")&nbsp; &nbsp; &nbsp; &nbsp; return self.fget(obj)&nbsp; &nbsp; def __set__(self, obj, value):&nbsp; &nbsp; &nbsp; &nbsp; if self.fset is None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise AttributeError("can't set attribute")&nbsp; &nbsp; &nbsp; &nbsp; self.fset(obj, value)&nbsp; &nbsp; def __delete__(self, obj):&nbsp; &nbsp; &nbsp; &nbsp; if self.fdel is None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise AttributeError("can't delete attribute")&nbsp; &nbsp; &nbsp; &nbsp; self.fdel(obj)&nbsp; &nbsp; def getter(self, fget):&nbsp; &nbsp; &nbsp; &nbsp; return type(self)(fget, self.fset, self.fdel, self.__doc__)&nbsp; &nbsp; def setter(self, fset):&nbsp; &nbsp; &nbsp; &nbsp; return type(self)(self.fget, fset, self.fdel, self.__doc__)&nbsp; &nbsp; def deleter(self, fdel):&nbsp; &nbsp; &nbsp; &nbsp; return type(self)(self.fget, self.fset, fdel, self.__doc__)

哆啦的时光机

文档说,这只是创建只读属性的捷径。所以@propertydef x(self):&nbsp; &nbsp; return self._x相当于def getx(self):&nbsp; &nbsp; return self._xx = property(getx)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python