Collections--ChainMap

  一个 ChainMap 类是为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理。它通常比创建一个新字典和多次调用 update() 要快很多。

class collections.ChainMap(*maps)

支持所有常用字典方法。另外还有一个 maps 属性(attribute),一个创建子上下文的方法(method), 一个存取它们首个映射的属性(property):

maps

  一个可以更新的映射列表。这个列表是按照第一次搜索到最后一次搜索的顺序组织的。它是仅有的存储状态,可以被修改。列表最少包含一个映射。

 

new_child(m=None)

  返回一个新的 ChainMap 类,包含了一个新映射(map),后面跟随当前实例的全部映射(map)。如果 m 被指定,它就成为不同新的实例,就是在所有映射前加上 m,如果没有指定,就加上一个空字典,这样的话一个 d.new_child() 调用等价于 ChainMap({}, *d.maps) 。这个方法用于创建子上下文,不改变任何父映射的值。

在 3.4 版更改: 添加了 m 可选参数。

 

parents

属性返回一个新的 ChainMap 包含所有的当前实例的映射,除了第一个。这样可以在搜索的时候跳过第一个映射。

 

 

现在假设你必须在两个字典中执行查找操作 (比如先从 a 中找,如果找不到再在 b中找)。一个非常简单扼解决方案就是使用 collections 模块中的 ChainMap 类。比如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In [46]: a = {'x': 1, 'z': 3 }                                                                                                      
 
In [47]: b = {'y': 2, 'z': 4 }                                                                                                      
 
In [48]: from collections import ChainMap                                                                                           
 
In [49]: c=ChainMap(a,b)                                                                                                            
 
In [50]: c.get('x')                                                                                                                 
Out[50]: 1
 
In [51]: c.get('z')                                                                                                                 
Out[51]: 3
 
In [52]: c.get('y')                                                                                                                 
Out[52]: 2

  如果出现重复键,那么第一次出现的映射值会被返回。因此,例子程序中的c['z']总是会返回字典a中对应的值,而不是b中对应的值。

 

对于字典的更新或删除操作总是影响的是列表中第一个字典。比如:
1
2
3
4
5
6
7
8
9
10
11
12
13
In [65]: c                                                                                                                          
Out[65]: ChainMap({'x': 1, 'z': 10}, {'y': 2, 'z': 4})
 
In [66]: c['x']=10                                                                                                                  
 
In [67]: c['z']=10                                                                                                                  
 
In [68]: c                                                                                                                          
Out[68]: ChainMap({'x': 10, 'z': 10}, {'y': 2, 'z': 4})
 
del c['y']
 
KeyError: "Key not found in the first mapping: 'y'"

  

一个 ChainMap 通过引用合并底层映射。 所以,如果一个底层映射更新了,这些更改会反映到 ChainMap 。

1
2
3
4
In [71]: a['x']=100                                                                                                                 
 
In [72]: c                                                                                                                          
Out[72]: ChainMap({'x': 100, 'z': 10}, {'y': 2, 'z': 4})

  

new_child()方法和parents属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
d=c.new_child()                                                                                                            
 
In [81]: d                                                                                                                          
Out[81]: ChainMap({}, {'x': 100, 'z': 10}, {'y': 2, 'z': 4})
 
In [82]: d['x']=1                                                                                                                   
 
In [83]: d                                                                                                                          
Out[83]: ChainMap({'x': 1}, {'x': 100, 'z': 10}, {'y': 2, 'z': 4})
 
In [84]: d=d.new_child()                                                                                                            
 
In [85]: d['x']=2                                                                                                                   
 
In [86]: d                                                                                                                          
Out[86]: ChainMap({'x': 2}, {'x': 1}, {'x': 100, 'z': 10}, {'y': 2, 'z': 4})
 
In [89]: d=d.parents                                                                                                                
 
In [90]: d['x']                                                                                                                     
Out[90]: 1
 
In [91]: d                                                                                                                          
Out[91]: ChainMap({'x': 1}, {'x': 100, 'z': 10}, {'y': 2, 'z': 4})
 
In [92]: d=d.parents                                                                                                                
 
In [93]: d['x']                                                                                                                     
Out[93]: 100

  

 

典型用例

让用户指定的命令行参数优先于环境变量,优先于默认值的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
import os, argparse
 
defaults = {'color': 'red', 'user': 'guest'}
 
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {k:v for k, v in vars(namespace).items() if v}
 
combined = ChainMap(command_line_args, os.environ, defaults)
print(combined['color'])
print(combined['user'])

  

 

posted @   头痛不头痛  阅读(419)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
历史上的今天:
2016-10-29 JavaWeb学习总结(五)—Myecplise的优化
点击右上角即可分享
微信分享提示
主题色彩