Python 3 map字典更新方法到其他字典列表
Python 3 map dictionary update method to a list of other dictionaries
在 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 将 return 一个迭代器(惰性求值等等),必须迭代它才能更新字典。
我原以为 d['c']
键查找会以某种方式触发映射迭代,但事实并非如此。
是否有一种 pythonic 方法可以在不编写 for 循环的情况下实现这种行为,
与地图相比,我发现它很冗长。
我想到了使用列表理解:
>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> [x for x in map(d.update, extras)]
>> d['c']
>> 4
但它看起来不像pythonic。
如您所见,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 的相关部分所说:
Particularly tricky is map()
invoked for the side effects of the
function; the correct transformation is to use a regular for
loop
(since creating a list would just be wasteful).
在你的情况下,这看起来像:
for extra in extras:
d.update(extra)
这不会导致不必要的列表 None
。
@jonrsharpe 的解释清楚地解释了问题在 Python 3 中,您可以使用 collections.ChainMap
来完成此类任务:
>>> from collections import ChainMap
>>> chain=ChainMap(d, *extras)
>>> chain
ChainMap({'a': 1}, {'b': 2}, {'c': 4})
>>> chain['c']
4
但请注意,如果有重复键,将使用 第一个 映射中的值。
阅读更多关于使用 ChainMap 的优势:What is the purpose of collections.ChainMap?
在 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 将 return 一个迭代器(惰性求值等等),必须迭代它才能更新字典。
我原以为 d['c']
键查找会以某种方式触发映射迭代,但事实并非如此。
是否有一种 pythonic 方法可以在不编写 for 循环的情况下实现这种行为, 与地图相比,我发现它很冗长。
我想到了使用列表理解:
>> d = {'a':1}
>> extras = [{'b':2}, {'c':4}]
>> [x for x in map(d.update, extras)]
>> d['c']
>> 4
但它看起来不像pythonic。
如您所见,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 的相关部分所说:
Particularly tricky is
map()
invoked for the side effects of the function; the correct transformation is to use a regularfor
loop (since creating a list would just be wasteful).
在你的情况下,这看起来像:
for extra in extras:
d.update(extra)
这不会导致不必要的列表 None
。
@jonrsharpe 的解释清楚地解释了问题在 Python 3 中,您可以使用 collections.ChainMap
来完成此类任务:
>>> from collections import ChainMap
>>> chain=ChainMap(d, *extras)
>>> chain
ChainMap({'a': 1}, {'b': 2}, {'c': 4})
>>> chain['c']
4
但请注意,如果有重复键,将使用 第一个 映射中的值。
阅读更多关于使用 ChainMap 的优势:What is the purpose of collections.ChainMap?