在谈论python中的类属性时,常见示例如下:
Python 2.7.6 (default, Sep 9 2014, 15:04:36)
>>> class B(object):
... cv = []
...
>>> b1 = B()
>>> b2 = B()
>>> b1.cv, b2.cv, B.cv
([], [], [])
>>> b1.cv.append(1)
>>> b1.cv, b2.cv, B.cv
([1], [1], [1])
>>> b2.cv.append(2)
>>> b1.cv, b2.cv, B.cv
([1, 2], [1, 2], [1, 2])
>>> B.cv.append(3)
>>> b1.cv, b2.cv, B.cv
([1, 2, 3], [1, 2, 3], [1, 2, 3])
它显示了class属性在class及其所有实例之间共享。
但是,当我们重新分配class属性的值时,即没有将初始对象的突变绑定到class属性时,会发生以下情况:
>>> class A(object):
... cv = 0
...
>>> a1 = A()
>>> a2 = A()
>>> a1.cv, a2.cv, A.cv
(0, 0, 0)
>>> a1.cv = 1
>>> a1.cv, a2.cv, A.cv
(1, 0, 0)
>>> a2.cv = 2
>>> a1.cv, a2.cv, A.cv
(1, 2, 0)
>>> A.cv = 3
>>> a1.cv, a2.cv, A.cv
(1, 2, 3)
在这里,我们可以看到每次该类属性存储其唯一值,并且不会在实例和类名称空间下应用的下一个赋值中覆盖它。
为什么这样的行为呢?
我不明白这种逻辑可能导致“不可变”(A)和“可变”(B)情况如此“不相关”的行为。
这使我想到“没有任何使用类变量的意义”,因为它们可能容易出错。
我希望那是我看不到这条隧道的光...
最佳答案
在第一个示例中,您对列表进行了变异。 Universe中只有一个列表实例B.__dict__['cv']
。在第二个示例中,您分配值。执行此操作时,将在每个特定的实例a(1|2|3)
中进行分配,因为这是Python中属性设置的工作方式(它将保存到您要更改其属性的任何内容的__dict__
中)。您必须修改A.cv
才能修改所有内容,并且在a(1|2|3)
中所做的任何更改都将覆盖所做的更改。
(Python尝试使用a(1|2|3).__dict__
,然后退回到A.__dict__
。)