@property装饰器在Python中如何工作? [英] How does the @property decorator work in Python?
问题描述
我想了解内置功能属性
的工作方式。令我感到困惑的是,属性
也可以用作修饰符,但仅当用作内置函数时才接受参数,而不能用作修饰符。
I would like to understand how the built-in function property
works. What confuses me is that property
can also be used as a decorator, but it only takes arguments when used as a built-in function and not when used as a decorator.
此示例来自文档 :
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.")
属性
的参数为 getx
, setx
, delx
和文档字符串。
property
's arguments are getx
, setx
, delx
and a doc string.
在属性以下的代码中
用作装饰器。它的对象是 x
函数,但是在上面的代码中,参数中没有对象函数的位置。
In the code below property
is used as decorator. The object of it is the x
function, but in the code above there is no place for an object function in the arguments.
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
<在这种情况下创建的code> x.setter 和 x.deleter
装饰器?
推荐答案
property()
函数返回一个特殊的描述符对象:
The property()
function returns a special descriptor object:
>>> property()
<property object at 0x10ff07940>
此对象具有 extra 个方法:
>>> 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>
这些也充当装饰器 。它们返回一个新的属性对象:
These act as decorators too. They return a new property object:
>>> property().getter(None)
<property object at 0x10ff079f0>
这是旧对象的副本,但是其中一个函数被替换。
that is a copy of the old object, but with one of the functions replaced.
记住, @decorator
语法只是语法糖;语法:
Remember, that the @decorator
syntax is just syntactic sugar; the syntax:
@property
def foo(self): return self._foo
的意思与
def foo(self): return self._foo
foo = property(foo)
so foo
该函数被 property(foo)
代替,我们在上面看到的是一个特殊的对象。然后,当您使用 @ foo.setter()
时,您正在做的就是调用 property()。setter
方法我在上面显示了您的信息,它返回了该属性的新副本,但这一次是将setter函数替换为装饰方法。
so foo
the function is replaced by property(foo)
, which we saw above is a special object. Then when you use @foo.setter()
, what you are doing is call that property().setter
method I showed you above, which returns a new copy of the property, but this time with the setter function replaced with the decorated method.
以下序列也创建了一个完整的-
The following sequence also creates a full-on property, by using those decorator methods.
首先,我们创建一些函数和一个仅带有吸气剂的 property
对象:
First we create some functions and a property
object with just a 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()
方法以添加设置器:
Next we use the .setter()
method to add a setter:
>>> prop = prop.setter(setter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is None
True
最后,我们使用<$ c $添加删除器c> .deleter()方法:
>>> prop = prop.deleter(deleter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is deleter
True
最后但并非最不重要的是,属性
对象充当描述符对象 ,因此它具有 .__ get __()
, .__ set __()
和 .__ delete __( )
方法,以获取,设置和删除实例属性:
Last but not least, the property
object acts as a descriptor object, so it has .__get__()
, .__set__()
and .__delete__()
methods to hook into instance attribute getting, setting and deleting:
>>> class Foo: pass
...
>>> prop.__get__(Foo(), Foo)
Get!
>>> prop.__set__(Foo(), 'bar')
Set to 'bar'!
>>> prop.__delete__(Foo())
Delete!
描述符方法包括类型为 property()
的纯Python示例实现:
The Descriptor Howto includes a pure Python sample implementation of the property()
type:
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__)
这篇关于@property装饰器在Python中如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!