该问题是由 python 选择通过引用传递列表这一事实引起的。
通常变量是“按值”传递的,因此它们独立运行:
>>> a = 1
>>> b = a
>>> a = 2
>>> print b
1
但由于列表可能变得相当大,Python 选择只使用引用(C 术语中的“指针”),而不是在内存中移动整个列表。如果将一个变量分配给另一个变量,则只需分配对其的引用。这意味着您可以有两个变量指向内存中的同一列表:
>>> a = [1]
>>> b = a
>>> a[0] = 2
>>> print b
[2]
所以,在你的第一行代码中你有4 * [0]
. Now [0]
是一个指向内存中值 0 的指针,当你乘以它时,你会得到四个指向内存中同一位置的指针。但是当你改变其中一个值时,Python 就知道指针需要改变以指向新值:
>>> a = 4 * [0]
>>> a
[0, 0, 0, 0]
>>> [id(v) for v in a]
[33302480, 33302480, 33302480, 33302480]
>>> a[0] = 1
>>> a
[1, 0, 0, 0]
当你乘以这个列表时,问题就出现了——你得到了列表指针的四个副本。现在,当您更改一个列表中的某个值时,所有四个值都会一起更改:
>>> a[0][0] = 1
>>> a
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
解决方案是避免第二次乘法。循环完成这项工作:
>>> some_list = [(4 * [0]) for _ in range(4)]