Python字典初始化?

Python字典初始化?,python,Python,我不确定这是一个bug还是一个特性。 我有一本字典要用空列表初始化 比方说 keys =['one','two','three'] sets = dict.fromkeys(keys,[]) 我观察到的是,如果您将任何项目附加到任何列表中,所有列表都会被修改 sets = dict.fromkeys(['one','two','three'],[]) sets['one'].append(1) 设置 但是当我使用循环手动执行时 for key in keys: sets[key]

我不确定这是一个bug还是一个特性。 我有一本字典要用空列表初始化

比方说

keys =['one','two','three']
sets = dict.fromkeys(keys,[])
我观察到的是,如果您将任何项目附加到任何列表中,所有列表都会被修改

sets = dict.fromkeys(['one','two','three'],[])
sets['one'].append(1)
设置

但是当我使用循环手动执行时

for key in keys:
      sets[key] = []
sets['one'].append(1)
设置


我认为第二种行为应该是默认行为。

这就是Python中的工作方式

以这种方式使用
fromkeys()
时,将以对同一列表的三个引用结束。当您更改一个列表时,所有三个列表都会发生更改

同样的行为也可以在这里看到:

In [2]: l = [[]] * 3

In [3]: l
Out[3]: [[], [], []]

In [4]: l[0].append('one')

In [5]: l
Out[5]: [['one'], ['one'], ['one']]
同样,这三个列表实际上是对同一列表的三个引用:

In [6]: map(id, l)
Out[6]: [18459824, 18459824, 18459824]

(注意他们是如何拥有相同的id的)

其他答案涵盖了“为什么”,下面是如何回答的

您应该使用理解来创建所需的词典:

>>> keys = ['one','two','three']
>>> sets = { x: [] for x in keys }
>>> sets['one'].append(1)
>>> sets
{'three': [], 'two': [], 'one': [1]}
对于Python 2.6及以下版本,字典理解可以替换为:

>>> sets = dict( ((x,[]) for x in keys) )

这个问题有很多不同的形式和形式。在这里,
collections.defaultdict
可能会为您提供最好的服务。声明如下:
sets=collections.defaultdict(list)
。为什么要对名为set的变量使用list而不是set?我发现,解释这一点最简单的方法是,它与执行
mylist=[]
后接
sets=dict.fromkeys(keys,mylist)
完全相同,就像在这种情况下一样,其中,
mylist
是每个键的值,当您传递一个空列表时,
[]
每次都是相同的空列表。这是因为在Python中,变量总是引用。这就是为什么
defaultdict
使用变量,而不是值本身。奇怪的是,
dict.fromkeys
没有遵循相同的技术。不奇怪的是,帮助说明:
dict.fromkeys(s[,v])->新的dict,其键来自s,值等于v。
@MikeyB我的意思是,如果它们以与
defaultdict
相同的方式实现
dict.fromkeys
,效果会更好。在当前的
dict.fromkeys实现中,编码人员必须使用一些迂回的方法来实现必要的功能。感谢您的评论。我发现这是python中的一个奇怪行为。否则,下面可能会有所帮助:
dict(zip(key,([]表示x在key中))
@MikeyB抱歉我的错误。另外,dict([(x,[])对于键中的x)不确定哪一个更快,生成器还是列表comp
>>> keys = ['one','two','three']
>>> sets = { x: [] for x in keys }
>>> sets['one'].append(1)
>>> sets
{'three': [], 'two': [], 'one': [1]}
>>> sets = dict( ((x,[]) for x in keys) )