2017-05-20 78 views
2

請,爲什麼這樣做Python的 - 如何解釋在這種情況下分配數據數組

array[0][0] = 'Tadaaaa' 

改變5個元素,而不是一看到下面的代碼?

首先,創建一個空數組:

x, y = 5, 3 

# when you multiply it's copying, so the ids of each item is the same 
array = [[set()] * y] * x 
array 

我將獲得:

[[set(), set(), set()], 
[set(), set(), set()], 
[set(), set(), set()], 
[set(), set(), set()], 
[set(), set(), set()]] 

然後將值分配給元素:

array[3][2].add('BBC') 
array 

我將獲得:

[[{'BBC'}, {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}]] 

但是當我做:

array[0][0] = 'Tadaaaa' 
array 

我得到:

[['Tadaaaa', {'BBC'}, {'BBC'}], 
['Tadaaaa', {'BBC'}, {'BBC'}], 
['Tadaaaa', {'BBC'}, {'BBC'}], 
['Tadaaaa', {'BBC'}, {'BBC'}], 
['Tadaaaa', {'BBC'}, {'BBC'}]] 

這是怎麼回事?

我想我會得到這樣的:

[['Tadaaaa', {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}], 
[{'BBC'}, {'BBC'}, {'BBC'}]] 
+0

如果會發生什麼你做([0],[0])呢? – alex

回答

5

首先,這些都不是數組;他們是名單。

二,用*造成對相同set的對象,而不是不同的set對象的引用列表的引用的列表。

>>> x = [set()]*3 
>>> id(x[0]), id(x[1]), id(x[2]) 
(4297985280, 4297985280, 4297985280) 

相反,使用列表理解,以確保set()每個元素調用一次。

>>> x = [set() for _ in range(3)] 
>>> id(x[0]), id(x[1]), id(x[2]) 
(4298169136, 4298363424, 4298363656) 

您可以使用嵌套列表理解來得到你想要的嵌套列表:

>>> x, y = 5, 3 
>>> array = [[set() for _ in range(y)] for _ in range(x)] 
>>> for x in array: 
... map(id, x) 
... 
[4298169136, 4298363424, 4298363656] 
[4297985280, 4298363888, 4298364120] 
[4298364352, 4298364584, 4298364816] 
[4298365048, 4298365280, 4298365512] 
[4298365744, 4298365976, 4298366208] 

正如你所看到的,陣列中的每個元素都是一個獨特的set對象。

+0

爲什麼'array [3] [2] .add('BBC')'改變所有元素,而array [0] [0] ='Tadaaaa''只改變一列? –

+2

因爲第一個調用'array [3] [2]'引用的可變對象的方法(這是與列表中的每個*元素引用的相同對象)。第二個改變存儲在'array [0] [0]'中的引用,用一個對'str'對象的引用覆蓋前一個引用。你應該閱讀https://nedbatchelder.com/text/names.html。 – chepner

+0

這是一篇很好的文章,可以更好地理解賦值。感謝分享chepner! – thatMeow

0

這是duplicate question,你是通過將重複相同的元素(空集):

array = [[set()] * y] * x 

您需要使用for環路初始化數組作爲一個解決方案 這是所有

+1

如果它是重複標記而不是回答它。 – MSeifert

+0

哦,是啊,我以爲我的聲望不允許,@ MSeifert –

+0

你不能即時關閉它作爲重複,但我認爲它只需要50聲望來標記它(和5正常標誌關閉的問題) – MSeifert

相關問題