3

我在 Spyder IDE 上测试了以下 python 代码。认为它会输出二维数组q,从 0..31q[0][0]q[3][7]。但它实际上返回 q 为:

[[24, 25, 26, 27, 28, 29, 30, 31], [24, 25, 26, 27, 28, 29, 30, 31], [24, 25, 26, 27, 28, 29, 30, 31], [24, 25, 26, 27, 28, 29, 30, 31]]. 

编码:

q=[[0]*8]*4 
for i in range(4): 
    for j in range(8): 
        q[i][j] = 8*i+j 
print q

知道这里发生了什么吗?我一步一步调试。它显示每一行的更新将与所有其他行同步,这与我对其他编程语言的体验完全不同。

4

3 回答 3

4
q=[somelist]*4 

创建一个包含四个相同项目的列表 list somelist。因此,例如,q[0]q[1]引用同一个对象。

因此,在嵌套的 for 循环q[i]中,无论i.

修理:

q = [[0]*8 for _ in range(4)]

列表推导评估[0]*84 个不同的时间,产生 4 个不同的列表。


下面是这个陷阱的快速演示:

In [14]: q=[[0]*8]*4

您可能认为您只更新了第二行中的第一个元素:

In [15]: q[1][0] = 100

但是你最终会改变每一行的第一个元素:

In [16]: q
Out[16]: 
[[100, 0, 0, 0, 0, 0, 0, 0],
 [100, 0, 0, 0, 0, 0, 0, 0],
 [100, 0, 0, 0, 0, 0, 0, 0],
 [100, 0, 0, 0, 0, 0, 0, 0]]
于 2012-09-02T13:03:00.307 回答
1

如前所述,问题是由于*对列表的操作引起的,这会创建对同一对象的更多引用。你应该做的是使用附加:

q=[]
for i in range(4): 
    q.append([])
    for j in range(8): 
        q[i].append(8*i+j)
print q 

[[0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23], [24, 25, 26, 27, 28, 29, 30, 31]]

于 2012-09-02T13:22:08.223 回答
0

当您执行类似的操作l = [x]*8时,实际上是在创建对相同的 8 个引用list,而不是 8 个副本。

要实际获得 8 个副本,您必须使用l = [[x] for i in xrange(8)]

>>> x=[1,2,3]
>>> l=[x]*8
>>> l
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> l[0][0]=10
>>> l
[[10, 2, 3], [10, 2, 3], [10, 2, 3], [10, 2, 3], [10, 2, 3], [10, 2, 3], [10, 2, 3], [10, 2, 3]]
>>> l = [ [x] for i in xrange(8)]
>>> l
[[[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]]]
>>> l[0][0] = 1
>>> l
[[1], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]], [[10, 2, 3]]]
于 2012-09-02T13:05:08.320 回答