Python 3将地图字典更新方法更新为其他字典列表

时间:2015-05-02 09:01:53

标签: python python-3.x python-2.7 dictionary map-function

在Python 2中,我可以执行以下操作:

>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> map(d.update, extras)
>> d['c']
>> 4

在Python 3中获取KeyError

>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> map(d.update, extras)
>> d['c']
>> KeyError: 'c'

我想在Python 3中实现与Python 2中相同的行为。

据我所知,Python 3中的map将返回一个迭代器(lazy evaluation and whatnot),必须迭代才能更新字典。

我假设d['c']键查找会以某种方式触发地图迭代,但事实并非如此。

有没有pythonic方法来实现这种行为而无需编写for循环, 与地图相比,我发现它是冗长的。

我想过使用列表推导:

>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> [x for x in map(d.update, extras)]
>> d['c']
>> 4

但它似乎并不像pythonic。

2 个答案:

答案 0 :(得分:7)

正如您所注意到的,Python 3中的map创建了一个迭代器,它不会(在其自身中)导致任何update发生:

>>> d = {'a': 1}
>>> extras = [{'b':2}, {'c':4}]
>>> map(d.update, extras)
<map object at 0x105d73c18>
>>> d
{'a': 1}

要强制map完全评估,您可以明确地将其传递给list

>>> list(map(d.update, extras))
[None, None]
>>> d
{'a': 1, 'b': 2, 'c': 4}

但是,正如What's new in Python 3的相关部分所说:

  

特别棘手的是map()被调用的副作用   功能;正确的转换是使用常规for循环   (因为创建列表只会浪费)。

在您的情况下,这看起来像:

for extra in extras:
    d.update(extra)

不会产生None的不必要列表。

答案 1 :(得分:1)

除了@ jonrsharpe的解释清楚地解释了问题在Python 3中,你可以使用collections.ChainMap来完成这些任务:

>>> from collections import ChainMap
>>> chain=ChainMap(d, *extras)
>>> chain
ChainMap({'a': 1}, {'b': 2}, {'c': 4})
>>> chain['c']
4

但请注意,如果存在重复键,则会使用 first 映射中的值。

详细了解使用ChainMap的优势:What is the purpose of collections.ChainMap?