为什么在父 class 中更改 'x' 的值只会更改一个子项的值?

Why does changing the value of 'x' in the parent class only change the value of one child?

在试验 python 时,我意识到此代码不会产生我预期的输出:

class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass


print Parent.x, Child1.x, Child2.x

Child1.x = 2
print Parent.x, Child1.x, Child2.x

Parent.x = 3
print Parent.x, Child1.x, Child2.x

以上代码的输出为:

1 1 1
1 2 1
3 2 3

为什么最后一行的输出是3 2 3而不是3 2 1?为什么改变Parent.x的值也会改变Child2.x的值,但同时不会改变Child1.x的值?

谢谢

当您分配给 Child1.x 时,您仅为 Child1 创建了一个新属性。但是,Child2 没有自己的 x 属性,因此它继承了 Parent 的版本,无论它的当前值是什么。

根据 class 中定义的属性,Python 具有写时复制行为。由于 Python 中的每个变量都是一个引用,在您将新值分配给 Child1.x 之前,Child1 中的 x 指的是 Parent.x.[=14 的值=]

事实上,您尝试做的通常是错误的做法!在您 真正 知道自己在做什么之前,您不应该将您计划稍后修改的 class 定义的变量放在一起。事实上,您的示例是 滥用 面向对象范式,因为您应该使用 classes 的实例,而不是 classes 本身。

评论中的更广泛的答案 如果将此添加到脚本的末尾

print Parent.__dict__
print Child1.__dict__
print Child2.__dict__

您可以详细了解 class 的所有成员以及存储在其中的内容。 输出将是

{'__dict__': <attribute '__dict__' of 'Parent' objects>, 'x': 3,    '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Parent' objects>, '__doc__': None}
{'x': 2, '__module__': '__main__', '__doc__': None}
{'__module__': '__main__', '__doc__': None}

正如您在 child1 中看到的那样
'x': 2 被添加到字典中。所以 child1 不会在它的父 class 中查找值,但是 child2 会