2013-03-20 61 views
27

这是导致我有点悲伤的...dict.fromkeys都指向同一个列表

我创建了一个字典从列表

l = ['a','b','c'] 
d = dict.fromkeys(l, [0,0]) # initializing dictionary with [0,0] as values 

d['a'] is d['b'] # returns True 

我怎样才能让字典中的每个值单独列表?这可能没有迭代所有的键,并将它们设置为一个列表?我想修改一个列表而不更改所有其他列表。

回答

25

你可以使用字典理解:

>>> keys = ['a','b','c'] 
>>> value = [0, 0] 
>>> {key: list(value) for key in keys} 
    {'a': [0, 0], 'b': [0, 0], 'c': [0, 0]} 
+1

'list(value)'和'value [:]'是同一件事吗? – Droogans 2014-04-20 01:56:54

+1

@Droogans:是的。我只是发现空白符号丑陋。 – Blender 2014-04-20 02:51:03

6

您可以使用此:

l = ['a', 'b', 'c'] 
d = dict((k, [0, 0]) for k in l) 
2
l = ['a','b','c'] 
d = dict((i, [0, 0]) for i in l) 
-4
keys = ['a','b','c'] 
value = [0, 0] 
d = dict.fromkeys(keys,value) 
print d 
# {'a':[0, 0], 'b':[0, 0], 'c':[0, 0]} 
+0

欢迎来到堆栈溢出!虽然这些规范可能会回答这个问题,但提供关于为什么和/或如何回答问题的附加背景将显着提高其长期价值。请[编辑]你的答案,添加一些解释。 – CodeMouse92 2016-04-19 19:01:15

+0

此答案无效。试试'd ['a']是d ['b']',你会发现它仍然是'真',这意味着它们都指向相同的数组。其他答案是正确的,因为每个键都有一个不同的数组副本 – 2016-04-19 20:23:50

4

这答案就在这里来解释这种行为对任何人对结果狼狈他们试图实例化dictfromkeys()与可变的默认值。

考虑:

#Python 3.4.3 (default, Nov 17 2016, 01:08:31) 

# start by validating that different variables pointing to an 
# empty mutable are indeed different references. 
>>> l1 = [] 
>>> l2 = [] 
>>> id(l1) 
140150323815176 
>>> id(l2) 
140150324024968 

所以任何变化l1不会影响l2,反之亦然。 对于任何可变的目前来说都是如此,包括dict

# create a new dict from an iterable of keys 
>>> dict1 = dict.fromkeys(['a', 'b', 'c'], []) 
>>> dict1 
{'c': [], 'b': [], 'a': []} 

这可以是一个方便的功能。 这里我们给每个键分配一个默认值,它也恰好是一个空列表。

# the dict has its own id. 
>>> id(dict1) 
140150327601160 

# but look at the ids of the values. 
>>> id(dict1['a']) 
140150323816328 
>>> id(dict1['b']) 
140150323816328 
>>> id(dict1['c']) 
140150323816328 

事实上,他们都使用相同的参考! 对一个人的改变是对所有人的改变,因为他们实际上是同一个对象!

>>> dict1['a'].append('apples') 
>>> dict1 
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']} 
>>> id(dict1['a']) 
>>> 140150323816328 
>>> id(dict1['b']) 
140150323816328 
>>> id(dict1['c']) 
140150323816328 

很多,这不是什么意图!

现在让我们试着将列表的显式副本用作默认值。

>>> empty_list = [] 
>>> id(empty_list) 
140150324169864 

,现在创建的empty_list副本的字典。

>>> dict2 = dict.fromkeys(['a', 'b', 'c'], empty_list[:]) 
>>> id(dict2) 
140150323831432 
>>> id(dict2['a']) 
140150327184328 
>>> id(dict2['b']) 
140150327184328 
>>> id(dict2['c']) 
140150327184328 
>>> dict2['a'].append('apples') 
>>> dict2 
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']} 

还是没有快乐! 我听到有人在喊,这是因为我用了一个空的名单!

>>> not_empty_list = [0] 
>>> dict3 = dict.fromkeys(['a', 'b', 'c'], not_empty_list[:]) 
>>> dict3 
{'c': [0], 'b': [0], 'a': [0]} 
>>> dict3['a'].append('apples') 
>>> dict3 
{'c': [0, 'apples'], 'b': [0, 'apples'], 'a': [0, 'apples']} 

fromkeys()默认行为是分配None的值。

>>> dict4 = dict.fromkeys(['a', 'b', 'c']) 
>>> dict4 
{'c': None, 'b': None, 'a': None} 
>>> id(dict4['a']) 
9901984 
>>> id(dict4['b']) 
9901984 
>>> id(dict4['c']) 
9901984 

事实上,所有的值是相同的(和唯一的!)None。 现在,让我们通过dict以无数种方式之一进行迭代并更改值。

>>> for k, _ in dict4.items(): 
... dict4[k] = [] 

>>> dict4 
{'c': [], 'b': [], 'a': []} 

嗯。看起来和以前一样!

>>> id(dict4['a']) 
140150318876488 
>>> id(dict4['b']) 
140150324122824 
>>> id(dict4['c']) 
140150294277576 
>>> dict4['a'].append('apples') 
>>> dict4 
>>> {'c': [], 'b': [], 'a': ['apples']} 

但他们确实不同[] s,在这种情况下,这是预期的结果。

+0

所以我们必须迭代? – user1712447 2018-01-25 02:46:51

相关问题