美文网首页大数据 爬虫Python AI SqlPython学习分享
在Python中合并字典模块ChainMap的隐藏坑

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

作者: 烟雨丿丶蓝 | 来源:发表于2019-06-27 14:45 被阅读12次

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

<pre class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">a = {'a': 1, 'b': 2}
b = {'x': 3, 'y': 4}
a.update(b)
print(a)
复制代码</pre>

运行效果如下图所示:

image

然而,这个方法有一个问题——它会改变其中一个字典。如果我们不想改变原有的两个字典,那么我们必需要单独再创建一个字典:

<pre class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">a = {'a': 1, 'b': 2}
b = {'x': 3, 'y': 4}
c = dict(a)
c.update(b)
print(c)
print(a)
复制代码</pre>

image

如果原来的两个字典非常大,那么这种方式将会浪费大量的内存。

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

答案就是 collections 模块下面的 ChainMap

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

例如:

<pre class="prettyprint hljs python" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">from collections import ChainMap
a = {'a': 1, 'b': 2}
b = {'x': 3, 'y': 4}
c = ChainMap(a, b)
print(c['a'])
print(c['y'])
复制代码</pre>

运行效果如下图所示:

image

不仅可以“合并”两个字典, ChainMap 可以接受任意多个字典,并把他们全都合在一起:

<pre class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">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'])
复制代码</pre>

运行效果如下图所示:

image

ChainMap 不会真的把字典合并在一起,而是在内部储存一个Key到每个字典的映射,当你读取 e[key] 的时候,它先去查询这个key在哪个字典里面,然后再去对应的字典里面查询对应的值。所以使用ChainMap几乎不需要额外的内存空间(当前这个对象自己会占用一些空间,但是如果要合并大字典,那么它自己占用的空间几乎可以忽略)。

所以你是不是觉得使用 ChainMap 就能实现完美合并字典了呢?

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

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

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

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

image

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

image

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

image

第四个问题,如果这个Key只在一个源字典中存在,那么这个Key会被从源字典中删除。如果这个Key在多个字典中都存在,那么Key会被从第一个字典中删除。当被从第一个字典中删除以后,第二个源字典的Key可以继续被 ChainMap 读取。

image

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

Python学习交流群:835017344,这里是python学习者聚集地,有大牛答疑,有资源共享!有想学习python编程的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入学习。

相关文章

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

    在Python中,当我们有两个字典需要合并的时候,可以使用字典的 update 方法,例如: a = {'a': ...

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

    在Python中,当我们有两个字典需要合并的时候,可以使用字典的 update 方法,例如: a = {'a': ...

  • python中defaultdict使用ChainMap合并字典

    最近在进行数据处理对字典进行合并,采用ChainMap方法,在查询时出现了一个问题,查询结果为空,排查子字典,该键...

  • Python 合并多个字典或映射

    合并多个字典或映射 ChainMap 假设有多个字典或者映射,需求是将这些字典或者映射,从逻辑上合并为一个单一的映...

  • urlparse解析url

    python3中urlparse模块和urllib模块合并,urlparse()在urllib.parse中进行调...

  • python合并字典

    python3和合并字典

  • python日常

    1. Python3中字典(dict)合并的几种方法 方法一:字典的update()方法 方法二:字典的dict(...

  • Python 小技巧

    1 Python: dict 小技巧 注意:Python 3 中的 dict 是有序的。 1.1 别样的合并字典技...

  • Python3 小技巧

    集合操作 字典操作 两个字典 相交、合并、相差 Python 映射 Python 内置函数 map();map()...

  • 字典

    字典 关键代码: 字典变种: OrderedDict保持添加顺序 ChainMap 多个map依次链接,越靠前优先...

网友评论

    本文标题:在Python中合并字典模块ChainMap的隐藏坑

    本文链接:https://www.haomeiwen.com/subject/xnhrcctx.html