+=
is the in-place addition operator. It does two things:
- it calls
obj.__iadd__(rhs)
to give the object the opportunity to mutate the object in-place.
- it rebinds the reference to whatever the
obj.__iadd__(rhs)
call returns.
By using +=
on a list stored in a tuple, the first step succeeds; the t[0]
list is altered in-place, but the second step, rebinding t[0]
to the return value of t[0].__iadd__
fails because a tuple is immutable.
The latter step is needed to support the same operator on both mutable and immutable objects:
>>> reference = somestr = 'Hello'
>>> somestr += ' world!'
>>> somestr
'Hello world!'
>>> reference
'Hello'
>>> reference is somestr
False
Here a immutable string was added to, and somestr
was rebound to a new object, because strings are immutable.
>>> reference = somelst = ['foo']
>>> somelst += ['bar']
>>> somelst
['foo', 'bar']
>>> reference
['foo', 'bar']
>>> reference is somestr
True
Here the list was altered in-place and somestr
was rebound to the same object, because list.__iadd__()
can alter the list object in-place.
From the augmented arithmetic special method hooks documentation:
These methods are called to implement the augmented arithmetic assignments (+=
, -=
, *=
, /=
, //=
, %=
, **=
, <<=
, >>=
, &=
, ^=
, |=
). These methods should attempt to do the operation in-place (modifying self
) and return the result (which could be, but does not have to be, self
).
The work-around here is to call t[0].extend()
instead:
>>> t = ([1,2],)
>>> t[0].extend([3, 4, 5])
>>> t[0]
[1, 2, 3, 4, 5]