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