4

我在 Python 中构建了一个二维向量,因为我一开始希望它全为零,并且不想使用 numpy,所以我尝试了这个:

columns = 8
rows = 5
m = [[0]* (columns)] * (rows)
m[3][2] = 1
print m

我得到了一个意想不到的行为:

>> [[0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0]]

看起来像这样构建二维数组,使每一行成为对单行的引用,所以如果写入其中任何一个,你就是在写入所有这些。

也许这对你们中的一些人来说听起来很明显,但我有点受不了。当然,我可以使用不同的方法来修复它,但我很好奇为什么会发生这种情况。

谁能解释一下?如果您使用 构建一个简单的数组,为什么不会发生这种情况[0] * size_of_array

4

3 回答 3

5

这是一个常见的 Python gothca。您不是在创建rows内部列表,而是在创建rows对同一列表的引用。

您的代码等效于以下内容:

inner_list = [0] * columns
m = [inner_list] * rows

我建议在不使用*运算符的情况下构建行。(您不会遇到与列有关的问题,因为0is 是 int 而 int 是不可变对象。)

matrix = []
for row in rows:
    matrix.append([0] * columns)
于 2013-07-03T15:55:17.657 回答
2

[0] * size_of_array creates a list which multiple references to 0. If you put another value into this list, it won't be affected.

As you noticed, [[]] * num creates a list which contains a reference to the same list over and over again. Of you change this list, the change is visible via all references.

>>> a = [0] * 10
>>> [id(i) for i in a]
[31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L, 31351584L]
>>> 
>>> all(i is a[0] for i in a)
True

vs.

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> [id(i) for i in a]
[44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L, 44072200L]
>>> all(i is a[0] for i in a)
True

Same situation, but one thing is different:

If you do a[0].append(10), the effect is visible in all lists.

But if you do a.append([]), you add a clean, new list which isn't related to the others:

>>> a = [[]] * 10
>>> a
[[], [], [], [], [], [], [], [], [], []]
>>> a.append([])
>>> a[0].append(8)
>>> a
[[8], [8], [8], [8], [8], [8], [8], [8], [8], [8], []]
>>> a[-1].append(5)
>>> a
[[8], [8], [8], [8], [8], [8], [8], [8], [8], [8], [5]]
于 2013-07-03T15:53:26.027 回答
1

当您执行 [[0] * 8] * 5 时,它不会创建包含 5 个对新对象的引用的列表。它首先创建 [0] * 8 对象(列表),然后将对该单个列表的引用分配给 * 5 创建的每个元素。

它相当于:

a = [ 0 ] * 8
b = [ a ] * 5
于 2013-07-03T15:55:42.547 回答