The +=
operator in python seems to be operating unexpectedly on lists. Can anyone tell me what is going on here?
class foo:
bar = []
Although much time has passed and many correct things were said, there is no answer which bundles both effects.
You have 2 effects:
+=
(as stated by Scott Griffiths)In class foo
, the __init__
method modifies the class attribute. It is because self.bar += [x]
translates to self.bar = self.bar.__iadd__([x])
. __iadd__()
is for inplace modification, so it modifies the list and returns a reference to it.
Note that the instance dict is modified although this would normally not be necessary as the class dict already contains the same assignment. So this detail goes almost unnoticed - except if you do a foo.bar = []
afterwards. Here the instances's bar
stays the same thanks to the said fact.
In class foo2
, however, the class's bar
is used, but not touched. Instead, a [x]
is added to it, forming a new object, as self.bar.__add__([x])
is called here, which doesn't modify the object. The result is put into the instance dict then, giving the instance the new list as a dict, while the class's attribute stays modified.
The distinction between ... = ... + ...
and ... += ...
affects as well the assignments afterwards:
f = foo(1) # adds 1 to the class's bar and assigns f.bar to this as well.
g = foo(2) # adds 2 to the class's bar and assigns g.bar to this as well.
# Here, foo.bar, f.bar and g.bar refer to the same object.
print f.bar # [1, 2]
print g.bar # [1, 2]
f.bar += [3] # adds 3 to this object
print f.bar # As these still refer to the same object,
print g.bar # the output is the same.
f.bar = f.bar + [4] # Construct a new list with the values of the old ones, 4 appended.
print f.bar # Print the new one
print g.bar # Print the old one.
f = foo2(1) # Here a new list is created on every call.
g = foo2(2)
print f.bar # So these all obly have one element.
print g.bar
You can verify the identity of the objects with print id(foo), id(f), id(g)
(don't forget the additional ()
s if you are on Python3).
BTW: The +=
operator is called "augmented assignment" and generally is intended to do inplace modifications as far as possible.