Python:Metaclass属性有时会覆盖类属性?

buk*_*zor 5 python metaclass

以下代码的结果令我难以置信:

class MyClass(type):
    @property
    def a(self):
        return 1

class MyObject(object):
    __metaclass__ = MyClass

    a = 2

print MyObject.a
print object.__getattribute__(MyObject, 'a')
print type.__getattribute__(MyObject, 'a')
print MyObject.__dict__['a']
print MyObject().a
Run Code Online (Sandbox Code Playgroud)

我真的希望这只是2重复打印,但它会打印出来1 1 1 2 2.有没有一种方法可以直观感觉?


澄清一下:我理解这种行为有很好的文档记录(这里是"数据描述符"),但我想了解为什么这有意义,以及核心开发人员为什么以这种方式实现描述符.

use*_*ica 3

属性是数据描述符;在属性查找中,它们优先于具有该属性的类实例的字典中的同名条目。这意味着与

MyObject.a
Run Code Online (Sandbox Code Playgroud)

a属性MyClass优先于的字典a中的条目MyObject。相似地,

object.__getattribute__(MyObject, 'a')
type.__getattribute__(MyObject, 'a')
Run Code Online (Sandbox Code Playgroud)

object.__getattribute__并且type.__getattribute__两者都尊重数据描述符相对于实例字典条目的优先级,因此该属性获胜。

另一方面,

MyObject.__dict__['a']
Run Code Online (Sandbox Code Playgroud)

这明确地进行了字典查找。它只看到MyObject's dict 中的内容,忽略正常的属性查找机制。

对于最后一行:

MyObject().a
Run Code Online (Sandbox Code Playgroud)

描述MyClass符仅适用于 的实例MyClass,而不是其实例的实例。属性查找机制看不到该属性。