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})
相关推荐
周全全5 分钟前
MySQL报错解决:The user specified as a definer (‘root‘@‘%‘) does not exist
android·数据库·mysql
Chef_Chen5 分钟前
从0开始机器学习--Day17--神经网络反向传播作业
python·神经网络·机器学习
白云如幻9 分钟前
MySQL的分组函数
数据库·mysql
百事老饼干9 分钟前
Java[面试题]-真实面试
java·开发语言·面试
customer0817 分钟前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
千澜空25 分钟前
celery在django项目中实现并发任务和定时任务
python·django·celery·定时任务·异步任务
荒川之神25 分钟前
ORACLE 闪回技术简介
数据库·oracle
2402_8575893627 分钟前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
HBryce2431 分钟前
缓存-基础概念
java·缓存