I was reading this interesting post https://asmeurer.github.io/blog/posts/tuples/
At the footnote author present this example
>>> t=1,2,[3,4]
>>> t
(1, 2, [3, 4])
>>> t[2]+=[5,6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
Although Python has raised a exception but it did change the tuple
>>> t
(1, 2, [3, 4, 5, 6])
Not sure what is going on here, is this a bug?
The behavior is same in 2.7.10 and 3.5.1
So the behavior of +=
is a bit weird. For immutable objects like integers it has to assign a new object to the same name:
a = 4
a += 3
For mutable types, e.g. lists, the object is altered in place, but also returns the same object to be assigned to the same name. The first step works with your tuple, but not the second.
That's why after the list is extended the exception is raised.
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__
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With