Python属性如何工作?

Fre*_*Foo 72 python properties

我已成功使用Python属性,但我不知道它们是如何工作的.如果我取消引用类之外的属性,我只得到一个类型的对象property:

@property
def hello(): return "Hello, world!"

hello  # <property object at 0x9870a8>
Run Code Online (Sandbox Code Playgroud)

但是如果我在一个类中放置一个属性,那么行为就会大不相同:

class Foo(object):
   @property
   def hello(self): return "Hello, world!"

Foo().hello # 'Hello, world!'
Run Code Online (Sandbox Code Playgroud)

我注意到unbound Foo.hello仍然是property对象,所以类实例化必须做出魔法,但那有什么神奇之处呢?

Tim*_*tes 50

正如其他人所说,他们使用称为描述符的语言功能.

通过类访问实际属性对象时返回的原因在于属性Foo.hello如何实现__get__(self, instance, owner)特殊方法:

  • 如果在实例上访问描述符,则该实例作为适当的参数传递,并且owner是该实例的.
  • 当通过类访问它时,instance则为None且仅owner传递.该property对象认识到这一点并返回self.

除了Descriptors howto之外,另请参阅语言指南中有关实现描述符调用描述符的文档.


Tim*_*ann 22

为了使@properties正常工作,该类需要是对象的子类.当类不是对象的子类时,第一次尝试访问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
Run Code Online (Sandbox Code Playgroud)

以下将正常工作

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
Run Code Online (Sandbox Code Playgroud)

  • 应该知道,从Python 3开始,不再需要从_object_继承. (24认同)
  • 更确切地说,在Python 3中,类默认情况下是从_object_继承的,因此无需在代码中明确编写。 (6认同)

Sve*_*ach 11

属性是描述符,描述符在类实例的成员时特别表现.简而言之,if a是一个类型的实例A,并且A.foo是一个描述符,那么a.foo相当于A.foo.__get__(a).

  • @larsmans:我做了一些快速测试.描述符本身的类型必须是新样式的类,否则它将不起作用.包含描述符的类无关紧要.上述引用可以用任何一种方式阅读. (2认同)