2017-04-05 32 views
0

嗨任何人都可以解釋爲什麼我們有以下行爲:Python的字典missmatch

>>> k = [0.5, 1, 2] 
>>> m = [0.5, 1, 2] 
>>> dict1 = dict.fromkeys(k, dict.fromkeys(m, 0)) 
>>> dict1 
{0.5: {0.5: 0, 1: 0, 2: 0}, 1: {0.5: 0, 1: 0, 2: 0}, 2: {0.5: 0, 1: 0, 2: 0}} 
>>> dict1[0.5][0.5]= 4.5 
>>> dict1 
{0.5: {0.5: 4.5, 1: 0, 2: 0}, 1: {0.5: 4.5, 1: 0, 2: 0}, 2: {0.5: 4.5, 1: 0, 2: 0}} 


>>> dict2 = {0.5: {0.5: 0, 1: 0, 2: 0}, 1: {0.5: 0, 1: 0, 2: 0}, 2: {0.5: 0, 1: 0, 2: 0}} 
>>> dict2[0.5][0.5] = 4.5 
>>> dict2 
{0.5: {0.5: 4.5, 1: 0, 2: 0}, 1: {0.5: 0, 1: 0, 2: 0}, 2: {0.5: 0, 1: 0, 2: 0}} 

所以在第一種情況下,每當我試圖改變dict1所有值的值具有相同第二個關鍵正在改變(例如dict1 [0.5] [0.5] = 4.5也會由於某些原因改變dict1 [1] [0.5])。

+1

由於'dict.fromkeys(m,0)'運行一次,然後在'dict.fromkeys(k,dict.fromkeys(m,0))'的每個值中放入相同的字典。你可以通過在dict1中使用dct來檢查:print id(dct)''它們都是相同的'id',例如。相同的'對象' – TemporalWolf

+2

只創建了一個子字典。你現在擁有的詞典本身可以通過多種方式訪問​​。 'dict [0.5]'和'dict [1]'是指同一個字典(而不是它的拷貝) – sgrg

回答

0

只創建了一個子字典。你現在擁有的詞典本身可以通過多種方式訪問​​。 dict[0.5]dict[1]指的是相同的字典(而不是它的副本)。

一個實現你想要做什麼樣的方式是使用字典理解:

dict1 = {k_outer: {k_inner:0 for k_inner in m} for k_outer in k} 

這會爲每個密鑰生成新的嵌套字典,從而避免它們的所有訪問同一個嵌套的字典問題。

1

我還沒有找到一個很好的欺騙目標,雖然這個普遍的問題是共同的:

因爲dict.fromkeys(m, 0)一次運行時函數被調用,然後把相同的單詞在每個值dict.fromkeys(k, dict.fromkeys(m, 0))。你可以通過做for dct in dict1: print id(dict1[dct])來檢查它們,它們都將是相同的id,例如。相同的對象:

>>> for dct in dict1: print id(dict1[dct]) 
140401847695352 
140401847695352 
140401847695352 

這是因爲參數只計算一次,當函數被調用 ...所以dict.fromkeys會把相同的值(無論那是)在每一個鍵。它等效於:

default_dct = dict.fromkeys(m, 0) 
dict1 = dict.fromkeys(k, default_dct) 

相反,您可以使用字典解析:

dict1 = {key: {ikey: 0 for ikey in m} for key in k} 

,或者通過複製:

inner_dct = dict.fromkeys(m, 0) 
dict1 = {} 
for key in k: 
    dict1[key] = inner_dct.copy() 

這兩者產生不同值:

>>>for dct in dict1: print id(dict1[dct]) 
140401847695352 
140401847646200 
140401847644240 
+0

這是否意味着,不可能在dict1中更改單個鍵?這是一個無賴。 – alDiablo

+0

@alDiablo它意味着你必須以不同的方式製作嵌套字典。 – TemporalWolf

+0

'dict.fromkeys'只能用於快速只讀字典嗎? – alDiablo