python collections 中的 ChainMap 类

ChainMap

chainMap 属于Python collections 模块下的一个子类,作用是将多个字典,组织成一个字典。当查询时,会按照构造时传入的字典的顺序进行查询。它比使用这些字典创建一个新字典要快。

简单示例

python 复制代码
# 导入ChainMap模块
from collections import ChainMap
h1 = {"a": 1, "b": 2, "c": 3}
h2 = {"a": 10, "b": 20, "d": 30}
# 将h1, h2组织成一个字典
h = ChainMap(h1, h2)
# 在第一个字典中查到了"a"这个key,返回该key对应的value
print(h["a"])
# 1
# 在第一个字典中没有查到了"a"这个key,然后在第二个字典的中查到了这个key,返回该key对应的value
print(h["d"])
#30

什么时候使用呢?

在Python中,配置文件通常是字典,系统配置和个人私有配置同时存在时候,可以使用ChainMap来构造出最终配置文件,构造时候个人私有配置在前,系统配置在后。这样,在使用的时候,个人配置就能覆盖系统配置。

常用操作

  • 初始化:chain_map = ChainMap(*maps)

    传入若干个字典,用来初始化。例如:chain_map = ChainMap(h1, h2)。这样就将多个字典组合在一起了。如果在初始化的时候,没有传入字典参数,则默认传入一个空字典。底层是将传入字典的引用保存在一个列表中。

  • 查询:查询时,依次查询每个字典,直到一个键被找到,并返回该值。

    python 复制代码
    from collections import ChainMap
    h1 = {"a": 1, "b": 2, "c": 3}
    h2 = {"a": 10, "b": 20, "d": 30}
    h = ChainMap(h1, h2)
    # 搜索操作会依次对字典进行搜索,返回第一个值
    print(h["a"])
    # 1
    print(h["d"])
    #30

    这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

  • 新增:新增键值对只操作第一个字典。

    python 复制代码
    from collections import ChainMap
    h1 = {"a": 1, "b": 2, "c": 3}
    h2 = {"a": 10, "b": 20, "d": 30}
    h = ChainMap(h1, h2)
    # 新增操作只会对第一个字典进行操作,因为保存的是引用,因此,本质上是原字典执行的新增操作
    h["x"] = 10000
    print(h)# 只对第一个字典进行新增
    # ChainMap({'a': 1, 'b': 2, 'c': 3, 'x': 10000}, {'a': 10, 'b': 20, 'd': 30})
    print(h1)
    # {'a': 1, 'b': 2, 'c': 3, 'x': 10000}

    这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

  • 更新:更新键值对只会操作第一个字典。

    python 复制代码
    from collections import ChainMap
    h1 = {"a": 1, "b": 2, "c": 3}
    h2 = {"a": 10, "b": 20, "d": 30}
    h = ChainMap(h1, h2)
    # 更新操作只会对第一个字典进行操作,因为保存的是引用,因此,本质上是原字典执行的更新操作
    h["a"] = 99
    print(h)
    # ChainMap({'a': 99, 'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30})
    print(h1)
    # {'a': 99, 'b': 2, 'c': 3}

    这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

  • 删除:删除键值对只会操作第一个字典。如果操作失败,会抛出异常。

    python 复制代码
    from collections import ChainMap
    h1 = {"a": 1, "b": 2, "c": 3}
    h2 = {"a": 10, "b": 20, "d": 30}
    h = ChainMap(h1, h2)
    # 删除操作只会对第一个字典进行操作,因为保存的是引用,因此,本质上是原字典执行的删除操作
    del h["a"]
    print(h)
    # ChainMap({'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30})
    print(h1)
    # {'b': 2, 'c': 3}
    del h["a"]
    # 抛出异常,因为只会对第一个字典进行操作,在一个字典中删除不存在的key抛出异常。(不会对后续字典进行操作)

    这样的目的是,让后面字典保持不变。例如第一个字典是私人配置,第二个字典是系统配置,操作只会影响个人配置,不会影响系统配置,这对于系统配置来说,是很重要的。

其他属性与操作

  • maps 属性:底层保存各个字典的列表。可以直接对该属性进行操作,实质是对原字典进行操作

    python 复制代码
    from collections import ChainMap
    h1 = {"a": 1, "b": 2, "c": 3}
    h2 = {"a": 10, "b": 20, "d": 30}
    h = ChainMap(h1, h2)
    print(h.maps)
    # [{'a': 1, 'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30}]
    # 使用该属性更改字典
    h.maps[0]["a"] = 123
    # 本质是改变原字典
    print(h1)
    # {'a': 123, 'b': 2, 'c': 3}     
  • new_child(m=None, **kwargs)方法:返回一个新的 ChainMap,字典m 位于第一位,其他位于后面,保存的是引用。如果没有指定m,相当于传入了一个空字典。调用 d.new_child() 等价于 ChainMap({}, *d.maps)。如果指定了任何关键字参数kwargs,它会更新所传入的字典。

    python 复制代码
    from collections import ChainMap
    h1 = {"a": 1, "b": 2, "c": 3}
    h2 = {"a": 10, "b": 20, "d": 30}
    h = ChainMap(h1, h2)
    # 传入的字典位于最前,传入的kwargs更新传入的字典
    hh = h.new_child({"a":-1}, b=10)
    # ChainMap({'a': -1, 'b': 10}, {'a': 1, 'b': 2, 'c': 3}, {'a': 10, 'b': 20, 'd': 30})
    print(hh)
  • parents属性:返回一个新的 ChainMap 对象,该对象等价于原对象去除了第一个字典。一个 d.parents 等价于 ChainMap(*d.maps[1:])

    python 复制代码
    from collections import ChainMap
    h1 = {"a": 1, "b": 2, "c": 3}
    h2 = {"a": 10, "b": 20, "d": 30}
    h = ChainMap(h1, h2)
    hh = h.parents
    print(hh)
    # ChainMap({'a': 10, 'b': 20, 'd': 30})
相关推荐
程序员小假7 分钟前
说一说 SpringBoot 中 CommandLineRunner
java·后端
Java Fans9 分钟前
如何在Windows本机安装Python并确保与Python.NET兼容
开发语言·windows·python
小邹子10 分钟前
抑郁症患者数据分析
python·信息可视化·数据分析
AI.NET 极客圈11 分钟前
.NET 原生驾驭 AI 新基建实战系列(四):Qdrant ── 实时高效的向量搜索利器
数据库·人工智能·.net
sky_ph16 分钟前
JAVA-GC浅析(一)
java·后端
爱coding的橙子17 分钟前
每日算法刷题Day24 6.6:leetcode二分答案2道题,用时1h(下次计时20min没写出来直接看题解,节省时间)
java·算法·leetcode
岁忧22 分钟前
(nice!!!)(LeetCode每日一题)2434. 使用机器人打印字典序最小的字符串(贪心+栈)
java·c++·算法·leetcode·职场和发展·go
隐藏用户_y25 分钟前
基于PyCharm推送代码到github实践记录
python
天天摸鱼的java工程师32 分钟前
@Autowired 注入失效?
java·后端
sss191s35 分钟前
校招 Java 面试基础题目解析学习指南含新技术实操要点
java·python·面试