This is because the +=
operator (which is __iadd__
, or in-place add internally) actually do return something after the assignment happened. In a list
this translates into an extend
call (or something like it) and thus the new items already got in, before the reference to the list was returned for assignment to t[2]
, which then raise the exception. Now you check the value you can see that it got added. The following is the minimum code to demonstrate this:
>>> class AddIDemo(object):
... def __init__(self, items):
... self.items = list(items)
... def __iadd__(self, other):
... print('extending other %r' % other)
... self.items.extend(other.items)
... print('returning self to complete +=')
... return self
... def __repr__(self):
... return self.items.__repr__()
...
>>> demo = AddIDemo([1, 2])
>>> demo += AddIDemo([3, 4])
extending other [3, 4]
returning self to complete +=
>>> demo
[1, 2, 3, 4]
>>> t = 1, 2, demo
>>> t
(1, 2, [1, 2, 3, 4])
>>>
>>> t[2] += AddIDemo([5, 6])
extending other [5, 6]
returning self to complete +=
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2, [1, 2, 3, 4, 5, 6])
>>>
Note that I added some more print statements to show that the function being called and how the operation happened as it would do in a standard list
manipulation via +=
or __iadd__
.