我已成功使用Python属性,但我看不出它们是如何工作的。如果我取消引用类之外的属性,我只会获得类型为property
的对象:
@property
def hello(): return "Hello, world!"
hello # <property object at 0x9870a8>
但是如果我在一个类中放置一个属性,行为就会大不相同了:
class Foo(object):
@property
def hello(self): return "Hello, world!"
Foo().hello # 'Hello, world!'
我注意到,未绑定的Foo.hello
仍然是property
对象,因此类实例化必须具有魔力,但这有什么神奇之处?
答案 0 :(得分:46)
正如其他人所说,他们使用一种称为描述符的语言功能。
通过类Foo.hello
访问实际属性对象时返回的原因在于属性如何实现__get__(self, instance, owner)
特殊方法:
owner
是该实例的类。 / LI>
instance
为无,仅传递owner
。 property
对象识别此内容并返回self
。除了Descriptors howto之外,另请参阅语言指南中有关Implementing Descriptors和Invoking Descriptors的文档。
答案 1 :(得分:21)
为了使@properties正常工作,该类必须是 object 的子类。 当类不是对象的子类时,那么当您第一次尝试访问setter时,它实际上会创建一个名称较短的新属性,而不是通过setter访问。
以下不正常工作。
class C(): # <-- Notice that object is missing
def __init__(self):
self._x = None
@property
def x(self):
print 'getting value of x'
return self._x
@x.setter
def x(self, x):
print 'setting value of x'
self._x = x
>>> c = C()
>>> c.x = 1
>>> print c.x, c._x
1 0
以下内容可以正常使用
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
print 'getting value of x'
return self._x
@x.setter
def x(self, x):
print 'setting value of x'
self._x = x
>>> c = C()
>>> c.x = 1
setting value of x
>>> print c.x, c._x
getting value of x
1 1
答案 2 :(得分:11)
属性为descriptors,描述符在类实例的成员时特别表现。简而言之,如果a
是A
类型的实例,而A.foo
是描述符,则a.foo
相当于A.foo.__get__(a)
。
答案 3 :(得分:3)
property
对象只实现了描述符协议:http://docs.python.org/howto/descriptor.html