Class variables are shadowed by instance attribute. This means that when looking up an attribute, Python first looks in the instance, then in the class. Furthermore, setting a variable on an object (e.g. self
) always creates an instance variable - it never changes the class variable.
This means that when, in your second example you do:
self.x += 1
which is (in this case, see footnote) equivalent to:
self.x = self.x + 1
what Python does is:
- Look up
self.x
. At that point, self
doesn't have the instance attribute x
, so the class attribute A.x
is found, with the value 10
.
- The RHS is evaluated, giving the result
11
.
- This result is assigned to a new instance attribute
x
of self
.
So below that, when you look up x.x
, you get this new instance attribute that was created in add()
. When looking up y.x
, you still get the class attribute. To change the class attribute, you'd have to use A.x += 1
explicitly – the lookup only happens when reading the value of an attribute.
Your first example is a classical gotcha and the reason you shouldn't use class attributes as "default" values for instance attributes. When you call:
self.x.append(1)
there is no assignment to self.x
taking place. (Changing the contents of a mutable object, like a list
, is not the same as assignment.) Thus, no new instance attribute is added to x
that would shadow it, and looking up x.x
and y.x
later on gives you the same list from the class attribute.
Note: In Python, x += y
is not always equivalent to x = x + y
. Python allows you to override the in-place operators separately from the normal ones for a type. This mostly makes sense for mutable objects, where the in-place version will directly change the contents without a reassignment of the LHS of the expression. However, immutable objects (such as numbers in your second example) do not override in-place operators. In that case, the statement does get evaluated as a regular addition and a reassignment, explaining the behaviour you see.
(I lifted the above from this SO answer, see there for more details.)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…