Python 奇怪的行为:“+=”创建别名

Python strange behavior: "+=" creates aliases

我无法解释这段代码的行为:

n=[[0,0],[0,0]]
m=n.copy()
for i in range(len(m)):
     m[i]+=[0]

我得到的输出是(不是我预期的):

>>> m
[[0, 0, 0], [0, 0, 0]]
>>> n
[[0, 0, 0], [0, 0, 0]]

如果我改为输入:

n=[[0,0],[0,0]]
m=n.copy()
for i in range(len(m)):
     m[i]=m[i]+[0]

我得到了正确的输出(这是我最初的预期):

>>> m
[[0, 0, 0], [0, 0, 0]]
>>> n
[[0, 0], [0, 0]]

所以,看起来如果我使用“+=”快捷方式,两个矩阵 "m" 和 "n" 就会变成别名。有人可以解释为什么会这样吗?

n.copy() 创建浅拷贝,因此 n[i]m[i] 已经指向同一个对象(尽管 mn 不同) .

对于列表,x += yx = x + y 完全不同 - 前者直接变异 x(相当于 x.extend(y)) 而后者将 x 分配给一个新值。

这两个事实共同解释了这种行为。

这里的区别在于 some_list += some_iterable 实际上与 some_list.extend(some_iterable) 相同。

some_list = some_list + [something_else] 实际上从 some_list[something_else] 连接在一起创建了一个新列表,然后将该新列表分配回 = 运算符的左侧.

当你这样想的时候,并且知道在复制之后,m[idx] is n[idx] for all 0 <= idx < len(m)1,就更容易明白为什么了+= 版本更改同时出现在 mn.

1list.copy() 进行 shallow 复制——这意味着它只复制引用。