2013-01-07 70 views
5

我正在学习Python,并一直试图使一个双动力。然而,我得到不正确的输出,我不知道为什么。我的代码如下:Python deque范围?

p = [2, 1], [1, 1] 
init_q= deque() 

init_q.append(p) 
for i in range(len(p)): 
    for j in range(len(p[i])): 
     temp = p[i][j] 
     p[i][j] = 0 
     init_q.append(p) 
     p[i][j] = temp 

while init_q: 
    print init_q.pop() 

在这段代码我需要在列表中,然后,我想创建一个队列5名单,其中有4个在不同的位置对他们有一个0,结果我要的是:

([2, 1], [1, 1]) 
([0, 1], [1, 1]) 
([2, 0], [1, 1]) 
([2, 1], [0, 1]) 
([2, 1], [1, 0]) 

但是,结果我得到的是:

([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
([2, 1], [1, 1]) 
+0

您确定预期的输出不是向后? – abarnert

回答

3

我通过简化代码在Python Tutor上创建了一个visualization。小提琴,你可以很容易地看到发生了什么。

单行更改为您的代码可以解决此问题。

init_q.append(map(list, p)) # Initialize a new list from p's element lists 

这里是visualization通过使用上述更改。

4

你把一个对象的双端队列,然后改变的对象。事实上,你总是把同一个对象放入deque中,所以所有的deque都是对一个对象p的引用。

+0

为了解决这个问题,你会......? –

+2

复制对象 - p [:]',或者如果不执行,则使用'copy'模块对列表进行'deepcopy',然后将* copy *附加到列表中。 – Volatility

+0

谢谢我不知道我在找什么,但我解决了。 'p [:]'不起作用,但是'deepcopy'没有。所以它现在看起来像: 'newobj = copy.deepcopy(p)' 'newobj [i] [j] = 0' 'init_q。append(newobj)' – Sjieke

1

跟进我对斯内德尔德的回答评论,这里是你如何能做到一成不变同样的事情:

for i in range(len(p)): 
    for j in range(len(p[i])): 
     temprow = [0 if y==j else p[i][y] for y in range(len(p[i]))] 
     temp = [temprow if x==i else p[x] for x in range(len(p))] 
     init_q.append(temp) 

在这种情况下,我认为结果比他的建议下少了很多可读:

 temp = copy.deepcopy(p) 
     temp[i][j] = 0 
     init_q.append(temp) 

正如我所说的,有时它会让事情变得更简单,有时更简单......但重点是更容易推理。您不必担心在init_q中是否有多个list - 或更差,在list s之内的子list s是共享标识。

这种权衡是否值得,实际上是一个个案的决定,每个程序员可能都不同。在这种情况下,我不会使用不可变的解决方案,并且我怀疑很多其他(Python)程序员会这样做。但值得知道如何编写它。

你也可以考虑把它写成一个3D列表,而不是2D列表的列表,然后将它送入deque。这显然相当,但在概念上它可能是简单的认为是这样的:

init_q.append(p) 
q = [copy.deepcopy(p) for i in range(len(p)) for j in range(len(p[i]))] 
for i in range(len(p)): 
    for j in range(len(p[i])): 
     q[i*len(p[i])+j][i][j] = 0 
init_q.extend(q) 

PS,如果你做了很多这样的事情,你可能想看看numpy。如果这是你的全部问题,那么它不会对你有任何好处......但是如果你对多维数组做任何更复杂的事情,它会。