Python字典初始化?
我不确定这是一个bug还是一个特性。 我有一本字典要用空列表初始化 比方说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]
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) )