a = [1, 2, 3]
a[-1] += a.pop()
This results in [1, 6].
a = [1, 2, 3]
a[0] += a.pop()
This results in
Using a thin wrapper around a list with debugging print-statements can be used to show the order of evaluation in your cases:
class Test(object):
def __init__(self, lst):
self.lst = lst
def __getitem__(self, item):
print('in getitem', self.lst, item)
return self.lst[item]
def __setitem__(self, item, value):
print('in setitem', self.lst, item, value)
self.lst[item] = value
def pop(self):
item = self.lst.pop()
print('in pop, returning', item)
return item
When I now run your example:
>>> a = Test([1, 2, 3])
>>> a[-1] += a.pop()
in getitem [1, 2, 3] -1
in pop, returning 3
in setitem [1, 2] -1 6
So it starts by getting the last item, which is 3, then pops the last item which is also 3, adds them and overwrites the last item of your list with 6. So the final list will be [1, 6].
And in your second case:
>>> a = Test([1, 2, 3])
>>> a[0] += a.pop()
in getitem [1, 2, 3] 0
in pop, returning 3
in setitem [1, 2] 0 4
This now takes the first item (1) adds it to the popped value (3) and overwrites the first item with the sum: [4, 2].
The general order of evaluation is already explained by @Fallen and @tobias_k. This answer just supplements the general principle mentioned there.