2012-06-07 160 views
3

我剛認識真是奇怪的Python的東西:爲什麼我不能改變只有一個元素嵌套列表在Python

>>> out=[[0]*3]*3 
>>> out 
[[0, 0, 0], [0, 0, 0], [0, 0, 0]] 
>>> out[0][1] 
0 
>>> out[0][1]=9 
>>> out 
[[0, 9, 0], [0, 9, 0], [0, 9, 0]] 

好,很明顯,我要的是:

[[0, 9, 0], [0, 0, 0], [0, 0, 0]] 

並不奇怪?我對Python並不是很熟悉,但Python總是以其直觀的行爲讓我印象深刻。但是它是如何出現的呢?
......我怎樣才能得到我需要的東西?

謝謝!

+0

你說得對一個事情 - 這不是很直觀。我不認爲他們用Python 3修正了它。 –

+0

@MarkRansom你爲什麼認爲這是需要**固定的**?如果你真的想要這樣的行爲,如果它發生了變化,那該怎麼辦呢? – jamylak

+1

對於任何人想知道如果人們在代碼中實際使用這種行爲,請參閱['zip()'](http://docs.python.org/library/functions.html#zip)上的文檔,它有一個示例使用'zip(* [iter(s)] * n)'將序列聚類成n長度的組。 –

回答

7

一個奇怪的行爲的確,但那只是因爲*操作使淺拷貝,你的情況 - [0, 0, 0]列表的淺拷貝。您可以使用id()功能,以確保這些內部名單實際上是相同的:

out=[[0]*3]*3 
id(out[0]) 
>>> 140503648365240 
id(out[1]) 
>>> 140503648365240 
id(out[2]) 
>>> 140503648365240 

悟可用於創建不同名單如下:

out = [ [0]*3 for _ in range(3) ] 
8

使用*複製列表中的元素是一個淺拷貝操作,所以你最終將與相同的可變對象的多個引用如果你使用這個包含可變對象名單。

相反,使用以下方法來初始化嵌套列表:

out = [[0]*3 for _ in range(3)] 

你可以看到,你的方法,在out每個條目實際上是同一列表的引用,這就是爲什麼你看到的行爲你做:

>>> out = [[0]*3]*3 
>>> out[0] is out[1] is out[2] 
True 
相關問題