Python ChainMap()


一、问题

合并多个字典或映射。



二、解决方案

在两个字典执行查找操作(先从 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})


posted @ 2021-12-02 22:16  做梦当财神  阅读(140)  评论(0编辑  收藏  举报