2013-01-07 66 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。如果這是你的全部問題,那麼它不會對你有任何好處......但是如果你對多維數組做任何更復雜的事情,它會。