Collections--ChainMap
一个 ChainMap
类是为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理。它通常比创建一个新字典和多次调用 update()
要快很多。
class collections.
ChainMap
(*maps)
支持所有常用字典方法。另外还有一个 maps 属性(attribute),一个创建子上下文的方法(method), 一个存取它们首个映射的属性(property):
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' ]) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于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的优化