普通list中元素的 += 操作
l = [i for i in range(5)] # [0,1,2,3,4]
tmp = l[0]
tmp += l[0]
对l无影响
但是对于如下嵌套的list时
l = [[0,0],[1,1]]
tmp = l[0]
tmp += l[0]
l 被修改为[[0,0,0,0],[1,1]]
而将 += 拆解则对原本list无影响
l = [[0,0],[1,1]]
tmp = l[0]
tmp = tmp + l[0]
解答:
Why does += behave unexpectedly on lists?
The general answer is that += tries to call the
__iadd__
special method, and if that isn’t available it tries to use__add__
instead. So the issue is with the difference between these special methods.
The__iadd__
special method is for an in-place addition, that is it mutates the object that it acts on. The__add__
special method returns a new object and is also used for the standard + operator.
So when the += operator is used on an object which has an__iadd__
defined the object is modified in place. Otherwise it will instead try to use the plain__add__
and return a new object.
That is why for mutable types like lists += changes the object’s value, whereas for immutable types like tuples, strings and integers a new object is returned instead (a += b becomes equivalent to a = a + b).
For types that support both__iadd__
and__add__
you therefore have to be careful which one you use. a += b will call__iadd__
and mutate a, whereas a = a + b will create a new object and assign it to a. They are not the same operation!
>>> a1 = a2 = [1, 2]
>>> b1 = b2 = [1, 2]
>>> a1 += [3] # Uses __iadd__, modifies a1 in-place
>>> b1 = b1 + [3] # Uses __add__, creates new list, assigns it to b1
>>> a2
[1, 2, 3] # a1 and a2 are still the same list
>>> b2
[1, 2] # whereas only b1 was changed
+=
是具有替代作用的操作符; 而对于 tuples, strings and integers 这类不可变变量,a+=b 等同于 a = a+b
从地址修改的角度解释:
>>> l = []
>>> id(l)
13043192
>>> l += [3]
>>> id(l)
13043192
>>> l = l + [3]
>>> id(l)
13059216