在Python中合并字典模块ChainMap的隐藏坑

在Python中,当咱们有两个字典须要合并的时候,可使用字典的update方法,例如:python

a = {'a': 1, 'b': 2}
b = {'x': 3, 'y': 4}
a.update(b)
print(a)
复制代码

运行效果以下图所示:微信

然而,这个方法有一个问题——它会改变其中一个字典。若是咱们不想改变原有的两个字典,那么咱们必须要单独再建立一个字典:spa

a = {'a': 1, 'b': 2}
b = {'x': 3, 'y': 4}
c = dict(a)
c.update(b)
print(c)
print(a)
复制代码

若是原来的两个字典很是大,那么这种方式将会浪费大量的内存。3d

不管是直接修改原有的其中一个字典,仍是建立另外一个字典,这两种方案都有点缺陷。那么有没有既不修改原有字典,又不另外建立一个新的字典的方法呢?code

答案就是collections模块下面的ChainMapcdn

使用ChainMap能够把多个字典合并成一个ChainMap对象。读写这个对象就像是读字典同样。对象

例如:blog

from collections import ChainMap
a = {'a': 1, 'b': 2}
b = {'x': 3, 'y': 4}
c = ChainMap(a, b)
print(c['a'])
print(c['y'])
复制代码

运行效果以下图所示:内存

不只能够“合并”两个字典,ChainMap能够接受任意多个字典,并把他们全都合在一块儿:string

from collections import ChainMap
a = {'a': 1, 'b': 2}
b = {'x': 3, 'y': 4}
c = {'z': 5, 'w': 6}
d = {'m': 7, 'h': 8, 'k': 9}
e = ChainMap(a, b, c, d)
print(e['a'], e['y'], e['z'], e['k'])
复制代码

运行效果以下图所示:

ChainMap不会真的把字典合并在一块儿,而是在内部储存一个Key到每一个字典的映射,当你读取e[key]的时候,它先去查询这个key在哪一个字典里面,而后再去对应的字典里面查询对应的值。因此使用ChainMap几乎不须要额外的内存空间(当前这个对象本身会占用一些空间,可是若是要合并大字典,那么它本身占用的空间几乎能够忽略)。

因此你是否是以为使用ChainMap就能实现完美合并字典了呢?

在使用它以前,你必定要理解它的运行原理。若是你理解了它的运行原理,那么下面几个问题,你在运行代码以前就会知道结果是什么:

  1. 若是两个字典里面有一个Key的名字相同,那么使用ChainMap之后会读取哪个?
  2. 若是为ChainMap对象添加一个Key-Value对,那么这个值会添加到哪里?
  3. 若是从原字典里面删除一个Key,ChainMap对象里面的Key也会消失吗?
  4. 若是从ChainMap对象里面删除一个Key,那么原字典里面的Key会消失吗?

首先来讲第一个问题的答案:

ChainMap对象会使用第一个拥有这个Key的字典里面的值,以下图所示:

第二个问题,新的Key-Value会被添加进第一个字典里面,以下图所示:

第三个问题,若是修改了原来的字典,那么ChainMap对象也会相应更新:

第四个问题,若是这个Key只在一个源字典中存在,那么这个Key会被从源字典中删除。若是这个Key在多个字典中都存在,那么Key会被从第一个字典中删除。当被从第一个字典中删除之后,第二个源字典的Key能够继续被ChainMap读取。

以上4点,在你使用ChainMap的时候必定要牢记,不然可能会致使你发现不了的Bug。

若是这篇文章对你有帮助,请关注个人微信公众号: 未闻Code(ID: itskingname),第一时间获的最新更新:

相关文章
相关标签/搜索