一、问题
合并多个字典或映射。
二、解决方案
在两个字典执行查找操作(先从 a 中找,找不到再从 b 中找)。
from collections import ChainMap
a = {'x': 1, 'z': 3}
b = {'y': 2, 'z': 4}
c = ChainMap(a, b)
print(c['x'])
print(c['y'])
print(c['z'])
输出:
1
2
3
三、讨论
1. ChainMap()
ChainMap
接受多个字典,将它们在逻辑上变为一个字典。事实并不是真的合并在一起。
ChainMap
类只是在内部创建一个容纳这些字典的列表,并重新定义了一些常见的字典操作来遍历这个列表。
print(len(c))
print(list(c.keys()))
print(list(c.values()))
输出:
3
['y', 'z', 'x']
[2, 3, 1]
出现重复键,第一次出现的值会被返回。因次,c['z']
是 a 中的值,不是 b 中的值。
对于字典的更新和删除,影响的总是列表中的第一个字典。
c['z'] = 10
c['w'] = 40
del c['x']
print(a)
del c['y']
输出:
{'z': 10, 'w': 40}
KeyError: "Key not found in the first mapping: 'y'"
new_child()
:
参数为空:在第一个位置插入一个空字典。
参数不为空:在第一个位置插入参数。
values = ChainMap()
values['x'] = 1
values = values.new_child()
values['x'] = 2
values = values.new_child()
values['x'] = 3
print(values)
print(values['x']) # 3
values = values.parents # 丢弃最近的字典
print(values['x']) # 2
values = values.parents
print(values['x'])
输出:
ChainMap({'x': 3}, {'x': 2}, {'x': 1})
3
2
1
2. update()
update()
也是将两个字典合并。
该方法会创建一个完全不同的字典对象(可能破坏现有的字典结构)。
原字典做更新,不会反映到合并的字典。
a = {'x': 1, 'z': 3}
b = {'y': 2, 'z': 4}
c = dict(a)
c.update(b)
print(c)
a['x'] = 13 # 原字典a做更新,不会反映到合并的字典c
print(c)
a.update(b) # 原字典做更新,所以合并的字典a也更新
print(a)
输出:
{'x': 1, 'z': 4, 'y': 2}
{'x': 1, 'z': 4, 'y': 2}
{'x': 13, 'z': 4, 'y': 2}
ChainMap
使用原来的字典,自己不创建新字典。所以不会产生上面的问题。
from collections import ChainMap
a = {'x': 1, 'z': 3}
b = {'y': 2, 'z': 4}
c = ChainMap(a, b)
a['x'] = 13
print(c)
输出:
ChainMap({'x': 13, 'z': 3}, {'y': 2, 'z': 4})