Python字典初始化?

use*_*385 4 python

我不确定这是一个错误还是一个功能.我有一个用空列表初始化的字典.

让我们说

keys =['one','two','three']
sets = dict.fromkeys(keys,[])
Run Code Online (Sandbox Code Playgroud)

我观察到的是,如果您将任何项目附加到任何列表中,则会修改所有列表.

sets = dict.fromkeys(['one','two','three'],[])
sets['one'].append(1)
Run Code Online (Sandbox Code Playgroud)

{'three': [1],'two': [1], 'one': [1]}
Run Code Online (Sandbox Code Playgroud)

但是当我手动使用循环时,

for key in keys:
      sets[key] = []
sets['one'].append(1)
Run Code Online (Sandbox Code Playgroud)

{'three': [], 'two': [], 'one': [1]}
Run Code Online (Sandbox Code Playgroud)

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

NPE*_*NPE 10

这就是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']]
Run Code Online (Sandbox Code Playgroud)

同样,这三个列表实际上是对同一列表的三个引用:

In [6]: map(id, l)
Out[6]: [18459824, 18459824, 18459824]
Run Code Online (Sandbox Code Playgroud)

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

  • 我发现,最简单的解释方法是它与`mylist = []`后跟`sets = dict.fromkeys(keys,mylist)`完全一样 - 就像在那种情况下,`mylist`是每个键的值,当你传递一个空列表`[]`时,它每次都是相同的空列表.原因是在Python中,变量总是引用. (2认同)
  • 这就是为什么`defaultdict` 使用[默认值工厂](http://docs.python.org/library/collections.html#collections.defaultdict.default_factory),而不是值本身。奇怪的是`dict.fromkeys` 没有遵循相同的技术。 (2认同)

Mik*_*eyB 5

其他答案涵盖了"为什么",所以这里是如何.

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

>>> keys = ['one','two','three']
>>> sets = { x: [] for x in keys }
>>> sets['one'].append(1)
>>> sets
{'three': [], 'two': [], 'one': [1]}
Run Code Online (Sandbox Code Playgroud)

对于Python 2.6及更低版本,字典理解可以替换为:

>>> sets = dict( ((x,[]) for x in keys) )
Run Code Online (Sandbox Code Playgroud)