Python中的collections模块(二) 有序字典OrderedDict和链接字典ChainMap

前言

Python 内置模块collections, 目标是提供各种专门的集合数据类型来解决特定的编程问题。

本系列介绍其中的数据结构特点和使用方法,  以便遇到某些特定的问题,可以找到对应的数据来处理, 达到事半功倍的效果

namedtuple用于创建其子类的工厂函数tuple,提供命名字段,允许按名称访问项目,同时保持按索引访问项目的能力
deque一个类似序列的集合,支持从序列的任一端有效地添加和删除项目
⭐OrderedDict根据插入键的时间保持键值对排序的字典子类
⭐ChainMap一个类似字典的类,允许将多个映射视为单个字典对象
defaultdict一个字典子类,用于为缺失的键构建默认值并自动将它们添加到字典中
Counter一个字典子类,支持方便地对序列或可迭代中的唯一项进行计数

本文介绍其中两个 OrderedDict,  ChainMap, 其他的可以参考

Python中的collections模块(一) 使用Counter,pythonic的对象计数方式

Python中的collections模块(三) 命名元组namedtuple和双端队列deque

Python中的collections模块(四) UserString,UserList,和UserDict

 1.Python中的dict与OrderedDict

多年来,Python字典都是无序的数据结构。当需要保持字典的内容有序的场景时, 需要一个一种新型字典。即OrderedDict

Python 3.6 及其以后的版本中, 内置dict类现在也保持其项目的有序性。下面简单介绍一下OrderedDict和dict的区别, 以及何时应该使用OrderedDict.

In [2]: from collections import OrderedDict

In [3]: od = OrderedDict()

In [4]: od['a']=1
In [5]: od['b']=2
In [6]: od['c']=3

# OrderedDict按照内容的添加顺序
In [7]: od
Out[7]: OrderedDict([('a', 1), ('b', 2), ('c', 3)])


In [8]: od2 = OrderedDict(a=1, b=2, c=3)
In [9]: od2
Out[9]: OrderedDict([('a', 1), ('b', 2), ('c', 3)])

 在Python3.6 之后,dict和OrderedDict基本相同

In [25]: dct = dict(a=1, b=2, c=3)
In [26]: od = OrderedDict(a=1, b=2, c=3)

# 数据均按被添加的顺寻保持有序
In [27]: dct.items() == od.items()
Out[27]: True

# 均可弹出最后一个item
In [28]: dct.popitem()
Out[28]: ('c', 3)
In [29]: od.popitem()
Out[29]: ('c', 3)

1.1 OrderedDict 特有方法 move_to_end()

OrderedDict和dict的显著区别是,多了一个方法 move_to_end(), 此方法支持将指定item移到字典的末尾或开头,是重新排序字典的神器. move_to_end的两个参数:

  1. key持有标识您要移动的项目的键。如果key不存在,那么你会得到一个KeyError.

  2. last保存一个bool值,该值定义您要将手头的项目移动到字典的哪一端。它默认为True, 移到最后; last=False时, 将item移到ordereddict的最前面.

In [38]: od = OrderedDict(a=1, b=2, c=3, d=4, e=5)

# 将'c' 移到最后
In [39]: od.move_to_end('c')
In [40]: od
Out[40]: OrderedDict([('a', 1), ('b', 2), ('d', 4), ('e', 5), ('c', 3)])

# 将'd' 移到最前
In [41]: od.move_to_end('d', last=False)
In [42]: od
Out[42]: OrderedDict([('d', 4), ('a', 1), ('b', 2), ('e', 5), ('c', 3)])

结论: 

  1. Python < 3.6 使用OrderedDict
  2. Python > 3.6 dict的顺序已经满足大部分场景, 需要重新排序的时候才考虑使用OrderedDict

 2.使用ChainMap管理多个上下文

ChainMap类可以将多个字典组合在一起,使它们在逻辑上显示并表现为一个整体。可以简单理解为高级的dict.update().

2.1 ChainMap与dict.update的区别

例如,我们现在有三个字典数据 dict1, dict2和dict3. 他们的key有交集

 经过update之后,会将原数据更新, 如执行dict2.update(dict1)之后会更新dict2的数据, 重复的key的数据会被覆盖.

ChainMap将多个字典逻辑上认为一个整体,内部包含每个字典的引用,并不直接修改源数据. 查找的时候逐层向下查找,知道最后一层还没有的话,抛出KeyError.

 2.2 ChainMap使用示例

In [1]: from collections import ChainMap

In [2]: dct1 = {'a': 1, 'b':2, 'c': 3}
In [3]: dct2 = {'c': 30, 'd': 40. 'e': 50}

In [4]: cm = ChainMap(dct1, dct2)
In [5]: cm
Out[5]: ChainMap({'a': 1, 'b': 2, 'c': 3}, {'c': 30, 'd': 40, 'e': 50})

# 读取时从左边第一个字典开始查找
In [6]: cm['c']
Out[6]: 3
In [6]: cm['e']
Out[6]: 50

# 修改只影响左边第一个字典
In [7]: cm['h'] = 66
In [8]: cm['e'] = 77
In [9]: cm
Out[9]: ChainMap({'a': 1, 'b': 2, 'c': 3, 'h': 66, 'e': 77}, {'c': 30, 'd': 40, 'e': 50})

 ChainMap提供访问各层数据的方法, 属性mapsparents

In [10]: cm.maps
Out[10]: [{'a': 1, 'b': 2, 'c': 3, 'h': 66, 'e': 77}, {'c': 30, 'd': 40, 'e': 50}]

In [11]: cm.maps[1]['c']=88
Out[11]: [{'a': 1, 'b': 2, 'c': 3, 'h': 66, 'e': 77}, {'c': 88, 'd': 40, 'e': 50}]

In [12]: cm.parents
Out[12]: ChainMap({'c': 88, 'd': 40, 'e': 50})

In [13]: cm.parents['d']=99
In [14]: cm
Out[14]: ChainMap({'a': 1, 'b': 2, 'c': 3, 'h': 66, 'e': 77}, {'c': 88, 'd': 99, 'e': 50})

new_child()方法, 在ChainMap外层链接新的字典

In [15]: cm.new_child({'x': 'xxx', 'y': 'yyy'})
Out[15]: ChainMap({'x': 'xxx', 'y': 'yyy'}, {'a': 1, 'b': 2, 'c': 3, 'h': 66, 'e': 77}, {'c': 30, 'd': 99, 'e': 50})

ChainMap适合将字典作为一个来管理,可以利用内部映射列表为字典中的重复键定义某种访问优先级。这就是为什么ChainMap对象非常适合处理多个上下文。

总结

本文介绍了 collections模块中的2中dict的拓展数据类型, OrderedDict和ChainMap.

OrderedDict为字典提供了顺序的功能, 并提高move_to_end方法来改变顺序.

ChainMap提供一个按照上下文使用多个字典中数据的方法.

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值