在Python中构建二维数组

时间:2013-07-03 15:46:24

标签: python arrays multidimensional-array

我在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构建一个简单的数组,为什么不会发生这种情况?

3 个答案:

答案 0 :(得分:5)

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

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

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

我建议不使用*运算符构建行。 (您不会遇到列的问题,因为0是一个int,而int是不可变对象。)

matrix = []
for row in rows:
    matrix.append([0] * columns)

答案 1 :(得分:2)

[0] * size_of_array创建一个列表,其中多个引用0。如果您在此列表中添加其他值,则不会受到影响。

正如您所注意到的,[[]] * num创建了一个列表,该列表一遍又一遍地包含对同一列表的引用。如果您更改此列表,则通过所有引用都可以看到更改。

>>> 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

同样的情况,但有一点是不同的:

如果您a[0].append(10),则效果在所有列表中都可见。

但是如果你做a.append([]),你添加一个与其他人无关的干净的新列表:

>>> 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]]

答案 2 :(得分:1)

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

相当于:

a = [ 0 ] * 8
b = [ a ] * 5