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})
相关推荐
董世昌4121 小时前
什么是事件冒泡?如何阻止事件冒泡和浏览器默认事件?
java·前端
好度1 天前
配置java标准环境?(详细教程)
java·开发语言
teacher伟大光荣且正确1 天前
关于Qt QReadWriteLock(读写锁) 以及 QSettings 使用的问题
java·数据库·qt
nightseventhunit1 天前
base64字符串String.getByte导致OOM Requested array size exceeds VM limit
java·oom
superman超哥1 天前
仓颉借用检查器工作原理深度解析
c语言·开发语言·c++·python·仓颉
钱彬 (Qian Bin)1 天前
项目实践13—全球证件智能识别系统(内网离线部署大模型并调用)
数据库·postgresql·fastapi·ubuntu24.04·离线部署·qwen3大模型
hgz07101 天前
索引的原理
数据库
悟能不能悟1 天前
java map判断是否有key,get(key)+x,否则put(key,x)的新写法
java·开发语言
张彦峰ZYF1 天前
Python 项目文件组织与工程化实践
python·项目文件组织与工程化实践
尋有緣1 天前
力扣614-二级关注者
大数据·数据库·sql·oracle