类变量 被 实例属性 遮盖
。这意味着在查找属性时,Python首先在实例中查找,然后在类中查找。此外,在对象(例如
self)上设置变量总是会创建一个实例变量-
它永远不会更改类变量。
这意味着在 第二个 示例中,当您执行以下操作时:
self.x += 1
(在这种情况下,请参见脚注)等效于:
self.x = self.x + 1
Python的作用是:
- 抬头
self.x
。那时,self
没有instance属性x
,所以A.x
找到了class属性,并带有value10
。 - 对RHS进行评估,得出结果
11
。 - 这一结果被分配到一个新的实例属性
x
中self
。
因此,在此之下,当您查找时
x.x,将获得在中创建的新实例属性
add()。查找时
y.x,您仍然会获得class属性。要更改class属性,您必须
A.x+= 1显式使用-仅在读取属性值时才进行查找。
您的 第一个 示例是经典的陷阱,您不应该将类属性用作实例属性的“默认”值的原因。你打电话的时候:
self.x.append(1)
没有任务
self.x要做。(更改可变对象(如)的
内容
list与分配是不同的。)因此,没有向其添加新的实例属性
x将其阴影化,然后在class属性中查找
x.x并
y.x稍后提供相同的列表。
注意: 在Python中,
x += y并不总是等同于
x = x + y。Python允许您针对类型将普通运算符与普通运算符分开覆盖。这对于
可变 对象来说最有意义,因为就地版本将直接更改内容 而无需 重新分配表达式的LHS。但是, 不可变的
对象(例如第二个示例中的数字)不会覆盖就地运算符。在这种情况下,该语句的确会被评估为常规加法和重新分配,从而说明您看到的行为。



