关于双循环的简单python代码

时间:2012-09-02 12:58:53

标签: python

我在Spyder IDE上测试了以下python代码。认为它将输出2d数组q作为从q[0][0]q[3][7]的0..31增加的数字。但它实际上将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

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

3 个答案:

答案 0 :(得分:4)

q=[somelist]*4 

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

因此,在嵌套for循环q[i]中引用相同的列表,而不管i的值。

修复:

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

列表推导评估[0]*8 4个不同的时间,产生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]]

答案 1 :(得分: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]]

  

答案 2 :(得分: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]]]