为什么以下抛出异常,虽然它成功了?
>>> 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)
>>>
Run Code Online (Sandbox Code Playgroud)
Neh*_*ani 17
在IRC上找到了答案.
t[0] += [1] 是几个离散的动作:
t[0]1它来建立一个新的列表[1]到什么t[0]是t[0]这似乎x += y基本上是x = x + y(但是,是吗?)
棘手的一点+=意味着分配给元组t和列表t[0]
t[0] += [1]不是字面意思 t[0] = t[0] + [1],它是:t[0] = t[0].__iadd__([1])
真正发生的是:
__iadd__都会改变列表并返回它.所以列表(它是第一个元素t)已经1附加到它上面了.为什么这在明显的视线中不可见?因为像我这样的n00b会期望t[0] += [1]一起成功或失败,因为它是python的一条短线.但情况并非总是如此.
通过查看字节码,它也可以帮助理解这种行为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
Run Code Online (Sandbox Code Playgroud)
t[0]放在堆栈顶部,BINARY_SUBSCR在这种情况下是一个(可变的)列表.+= [1]在其上执行INPLACE_ADD,在这种情况下,堆栈的顶部引用元组内的列表.t[0]在堆栈顶部的赋值发生时STORE_SUBSCR,由于t本身是一个不可变的元组,因此失败,在赋值已经发生之后引发错误+=.