3

这段代码应该打印什么?

class Parent():
    class Meta(object):
        classattr = "Hello"

class Child(Parent):
    pass


Child.Meta.classattr = "world"


ch = Child()
pr = Parent()

ch.Meta.classattr = "Oppa"

print Parent.Meta.classattr
print Child.Meta.classattr

print pr.Meta.classattr
print ch.Meta.classattr

我期望以下:

Hello
world
Hello
Oppa

但是得到了

Oppa
Oppa
Oppa
Oppa

所以...我可以通过修改子类实例来修改父类(不是实例!)。这正常吗?

4

3 回答 3

6

Child.Meta实际上 Parent.Meta- 类Child没有自己的Meta类属性,因此属性的查找规则解析为Parent.Meta. 此外,由于它是一个类属性,因此对 of 的实例Parent(包括 的实例Child)的任何查找都将解析为相同的类对象。

于 2013-12-23T18:58:10.697 回答
1

我将尝试解释这里发生的事情:

class Parent():
    class Meta(object):
        classattr = "Hello"

class Child(Parent):
    pass


Child.Meta.classattr = "world"

在这里,您将“世界”分配给classattrMeta。如果 Meta 最初是在 Parent 内部定义的,则无关紧要;Child 和 Parent 共享相同 Meta的.

ch = Child()
pr = Parent()

ch.Meta.classattr = "Oppa"

在这里,您将“世界”分配给classattrMeta。ch是否是一个实例并不重要。Meta 始终是同一个对象。

print Parent.Meta.classattr
print Child.Meta.classattr

print pr.Meta.classattr
print ch.Meta.classattr

在这里,您正在打印相同classattr的Meta。

于 2013-12-23T19:00:42.527 回答
0

我认为最直接的解释是元类只是一个type由 引用的普通对象(类型)Parent,子类化和实例化不会复制元类,而只是创建对它的新引用(或者严格来说实际上甚至不是——它只是属性查找如何工作)。因此,无论何时将新值存储到classattr中,实际上都是在修改同一对象的相同属性。

于 2013-12-23T19:03:41.327 回答