Why does the following throw an exception, although it succeeds?
>>> t = ([1, 2, 3], 4)
>>> t[0] += [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> t
([1, 2, 3, 1], 4)
>>>
You can directly enter duplicate items in a Python tuple as it doesn't behave like a set(which takes only unique items).
The repetition operator makes multiple copies of a tuple and joins them all together. Tuples can be created using the repetition operator, *.
copy. copy() and copy. deepcopy() just copy the reference for an immutable object like a tuple.
Once a tuple is created, you cannot change its values. Tuples are unchangeable, or immutable as it also is called.
Found the answer on IRC.
t[0] += [1]
is several discrete actions:
t[0]
1
in it[1]
to whatever t[0]
ist[0]
It seems that x += y
is basically x = x + y
(but, is it?)
The tricky bit is that +=
implies assignment to both the tuple t
and to the list t[0]
t[0] += [1]
is not literally t[0] = t[0] + [1]
, it is: t[0] = t[0].__iadd__([1])
What really happens is:
__iadd__
both mutates the list and returns it. So the list (which is the first element in t
) has already got 1
appended to it.Why is this not visible in plain sight? Because a n00b like me would expect t[0] += [1]
to either succeed all together or fail, because it's one short line of python. But that's not always the case.
It can also help to understand this behavior by taking a look at the bytecode with dis.dis
.
In[5]: dis('t[0] += [1]')
1 0 LOAD_NAME 0 (t)
3 LOAD_CONST 0 (0)
6 DUP_TOP_TWO
7 BINARY_SUBSCR
8 LOAD_CONST 1 (1)
11 BUILD_LIST 1
14 INPLACE_ADD
15 ROT_THREE
16 STORE_SUBSCR
17 LOAD_CONST 2 (None)
20 RETURN_VALUE
t[0]
is placed on top of the stack with BINARY_SUBSCR
, which is a (mutable) list in this case. += [1]
performed on it with INPLACE_ADD
, where in this case the top of the stack refers to the list inside the tuple. t[0]
to the top of the stack occurs with STORE_SUBSCR
, which fails here as t
itself is an immutable tuple, raising the error after the +=
assignment has already occurred. 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