2012-06-03 57 views
2

我已經建立了一個3級嵌套列表Python列表錯誤還是我錯了?

#run on Python 3.2.3 32 bit on Win 7 
L2=list(0 for i in range(2)) 
L3=list(L2 for i in range(3)) 
L4=list(L3 for i in range(4)) 
#give a new value to the very first number in list: 
L4[0][0][0]=5 
print("L4:") 
print(L4) 
#outputs erronously: 
#[[[5, 0], [5, 0], [5, 0]], [[5, 0], [5, 0], [5, 0]], [[5, 0], [5, 0], [5, 0]], [[5, 0], [5, 0], [5, 0]]] 

明確給出

#the same L4 given explicitly: 
anotherL4=[[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]] 
print("anotherL4:") 
#give a new value to the very first number: 
anotherL4[0][0][0]=5 
print(anotherL4) 
#outputs correctly: 
#[[[5, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]] 
+0

+1考慮到你可能是錯的。 –

回答

3

你錯了相同的列表。您已多次複製參考,這意味着它們實際上都是相同的列表。

3

當你編寫list(L3 for i in range(4))時,你告訴它在發生器理解的每次迭代中產生相同的列表L3。當您隨後修改該列表時,這些修改無處不在,因爲它們都是對同一列表的引用。

你可以得到的效果,你似乎做

list(list(L3) for i in range(4)) 

因爲使用list(L3)使得一個新的列表來想。

+0

或只是'[list(L3)for i in range(4)]' – jamylak

0

只是爲了闡述,

a = 1 
b = 2 
c = [a,b] 
a += 1 
print c 
0

你的問題是你建的列表的引用列表而不是列表的列表。由於引用都指向單個列表,因此當您更改單個列表時,所有引用都會顯示更改。

L0 = range(3) 
L1 = range(3) 

print(id(L0)) # prints a number 
print(id(L1)) # prints a different number 
print(id(L0) == id(L1)) # prints False 

print(L0 is L1) # prints False; not same objects 
print(L0 == L1) # prints True; values match 

# your original code: 
L2=list(0 for i in range(2)) 
L3=list(L2 for i in range(3)) 
L4=list(L3 for i in range(4)) 

print(L3[0] is L2) # prints True; L3[0] is a reference to L2 

我們能解決這個問題,並明確表明我們正在利用copy.deepcopy()做:

import copy 

L2 = [0 for i in range(2)] 
L3 = [copy.deepcopy(L2) for i in range(3)] 
L4 = [copy.deepcopy(L3) for i in range(4)] 
#give a new value to the very first number in list: 
L4[0][0][0]=5 
print("L4:") 
print(L4) 

注意,而不是使發電機表達並將它傳遞給list()迫使它擴展出一個列表,我只是在上面的代碼中使用了list comprehensions來直接創建列表。

更通常,如果你想這樣做瘋狂的事情,你應該也許只是窩一些列表內涵:

L4 = [[[0 for _ in range(2)] for _ in range(3)] for _ in range(4)] 

這使得它非常清楚,我們正在建立列表的列表的新列表。如果你使用copy.deepcopy(),你基本上只是複製一堆零,所以你不妨使用零創建新列表。

+0

(如BrenBarn的解決方案所示)使用'list(L2)'是克隆列表的一種更好的方法(特別是因爲這只是一個簡單的列表整數)。爲此,導入'deepcopy'是沒有必要的。 –

+0

@shuzOMGchen,我的實際建議的解決方案是最後一個。我認爲,爲了教育目的,明確調用Python複製函數的清晰度是值得的。如果沒有'copy.deepcopy()',你就無法正確構建'L4';你可以用'list(L2)'建立'L3',但如果你在建立'L4'時嘗試重複這個模式,你會重複一些引用。如我所展示的那樣,只需構建您想要的零列表更簡單,但如果您確實必須不斷重新複製嵌套列表,則需要複製嵌套列表的方法。 – steveha

相關問題