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

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

这个例子来自文档:

class C(object):

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(object):

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.setterx.deleter装饰器是如何创建的?我很困惑。

回答:

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-@property装饰器如何工作? 的全部内容, 来源链接: utcz.com/qa/421500.html

回到顶部