这是我的代码:
In [8]: b=dict.fromkeys([1,2,3,4], [])
In [9]: b[1].append(1)
In [10]: b[2].append(2)
In [11]: b[1]
Out[11]: [1, 2]
In [12]: b[2]
Out[12]: [1, 2]
In [13]: b
Out[13]: {1: [1, 2], 2: [1, 2], 3: [1, 2], 4: [1, 2]}
我希望:{1:[1],2:[2],3:[],4:[]}
我想这可能是由于b [X]只是一个“引用”引起的,它们都是指同一个列表。
然后我用int对象替换[]。结果让我更加困惑:
In [15]: b=dict.fromkeys([1,2,3,4], 1)
In [16]: b[1] += 1
In [17]: b[2] += 1
In [18]: b
Out[18]: {1: 2, 2: 2, 3: 1, 4: 1}
在这种情况下,此int对象1不是referance。
然后我用['a']替换[]:
In [19]: b=dict.fromkeys([1,2,3,4], ['a'])
In [20]: b[1].append(1)
In [21]: b[2].append(2)
In [22]: b
Out[22]: {1: ['a', 1, 2], 2: ['a', 1, 2], 3: ['a', 1, 2], 4: ['a', 1, 2]}
现在['a']再次作为参考。
有人可以告诉我为什么,以及如何在第一种情况下获得预期结果“{1:[1],2:[2],3:[],4:[]}”。
赞赏任何有用的建议。
答案 0 :(得分:6)
因为dict中的所有值实际上都是对同一列表的引用,dict.fromkeys
使用相同的列表对象并将其分配给每个键。由于list.append
是就地操作,因此所有密钥都会受到影响。
>>> b = dict.fromkeys([1,2,3,4], [])
>>> [id(x) for x in b.values()]
[158948300, 158948300, 158948300, 158948300]
因此,对于可变值,使用dict理解:
>>> b = {k:[] for k in xrange(1, 5)}
>>> [id(x) for x in b.values()]
[158945580, 158948396, 158948108, 158946764]
或者@Bakuriu建议,collections.defaultdict
也可以正常工作:
>>> from collections import defaultdict
>>> dic = defaultdict(list)
>>> dic[1].append(1)
>>> dic[2].append(2)
>>> dic
defaultdict(<type 'list'>, {1: [1], 2: [2]})
>>> dic[3]
[]
答案 1 :(得分:4)
他们真的都是参考。区别在于您对引用的处理方式。
使用赋值运算符=
时,您将设置对其他对象的引用。 (+=
的工作方式相同)。
使用append
时,您正在修改对象而不影响引用。由于fromkeys
回复了对同一对象的多个引用,因此可以同时在所有对象中看到修改。