a = [1, 2, 3]
a[-1] += a.pop()
This results in [1, 6]
.
a = [1, 2, 3]
a[0] += a.pop()
This results in
Let's have a look at the output of dis.dis for a[-1] += a.pop()
1):
3 15 LOAD_FAST 0 (a) # a,
18 LOAD_CONST 5 (-1) # a, -1
21 DUP_TOP_TWO # a, -1, a, -1
22 BINARY_SUBSCR # a, -1, 3
23 LOAD_FAST 0 (a) # a, -1, 3, a
26 LOAD_ATTR 0 (pop) # a, -1, 3, a.pop
29 CALL_FUNCTION 0 (0 positional, 0 keyword pair) # a, -1, 3, 3
32 INPLACE_ADD # a, -1, 6
33 ROT_THREE # 6, a, -1
34 STORE_SUBSCR # (empty)
The meaning of the different instructions is listed here.
First, LOAD_FAST
and LOAD_CONST
load a
and -1
onto the stack, and DUP_TOP_TWO
duplicates the two, before BINARY_SUBSCR
gets the subscript value, resulting in a, -1, 3
on the stack. It then loads a
again, and LOAD_ATTR
loads the pop
function, which is called with no arguments by CALL_FUNCTION
. The stack is now a, -1, 3, 3
, and INPLACE_ADD
adds the top two values. Finally, ROT_THREE
rotates the stack to 6, a, -1
to match the order expected by STORE_SUBSCR
and the value is stored.
So, in short, the current value of a[-1]
is evaluated before calling a.pop()
and the result of the addition is then stored back to the new a[-1]
, irrespective of its current value.
1) This is the disassembly for Python 3, slightly compressed to better fit on the page, with an added column showing the stack after # ...
; for Python 2 it looks a bit different, but similar.