I'm trying to modify a list in a tuple, the append method works, while += operator works yet with an exception raised saying tuple could not be modified. I know a tuple is immutable, but I'm not trying to mutate it. Why this happen?
In [36]: t=([1,2],)
In [37]: t[0].append(123)
In [38]: t
Out[38]: ([1, 2, 123],)
In [39]: t[0]+=[4,5,]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-39-b5b3001fbe03> in <module>()
----> 1 t[0]+=[4,5,]
TypeError: 'tuple' object does not support item assignment
In [40]: t
Out[40]: ([1, 2, 123, 4, 5],)
+= is the in-place addition operator. It does two things:
obj.__iadd__(rhs) to give the object the opportunity to mutate the object in-place.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 (modifyingself) 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]
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