2017-04-05 96 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