Python--collections容器数据类型

collections模块基本介绍

我们都知道,Python拥有一些内置的数据类型,比如str、list、tuple、dict等,collections模块是在这些内置数据类型的基础上,提供了几个额外的数据类型,以提供Python标准内建容器dict、list、set、tuple的替代选择。主要有:

  1. namedtuple:生成可以使用名字来访问元素内容的tuple子类
  2. deque: 双端队列,可以快速的从另外一侧追加和推出对象
  3. Counter: 计数器,主要用来计数
  4. OrderedDict: 有序字典
  5. defaultdict: 带有默认值的字典

这些数据类型的作用主要有增加代码的可读性、方便用户操作数据、提高某些场景下数据的访问效率。

本文中的代码是在交互终端执行,>>> 是输入的执行代码,代码下面跟的是运行结果。

1、nametuple()

namedtuple主要用来产生可以使用名称来访问元素的数据对象,通常用来增强代码的可读性, 在访问一些tuple类型的数据时尤其好用。

比如你想用一个数据类型保存一个三维空间里的点坐标,可以直接用普通元祖来保存点的三个坐标(x, y, z),这样像获取某个坐标时只能通过索引来获取。而用nametuple来保存三维点的坐标非常方便。

首先导入相关包:

1
>>> from collections import namedtuple

定义一个namedtuple数据类型,名为Point,之后我们就可以利用Point直接创建数据。

1
2
3
4
5
6
7
8
>>> Point = namedtuple('Point', ['x', 'y', 'z'])
>>> p1 = Point(2, 5, 8) # 创建一个点
>>> p1
Point(x=2, y=5, z=8)
>>> p1.x
2
>>> type(p1)
<class '__main__.Point'>

可以看出定义的Point类型是继承了namedtuple的一个类。可以直接通过p1.x 访问点的x坐标。

接着我们对p1点做一些进一步的操作。常用的函数有:

  • Point._make():利用list或迭代实例生成namedtuple
1
2
3
4
>>> b = [12, 5, 10]
>>> p2 = Point._make(b)
>>> p2
Point(x=12, y=5, z=10)
  • Point._asdict():返回一个新的dict,它将字段名称映射到它们对应的值
1
2
3
4
5
6
>>> d = Point._asdict(p2)
>>> d
OrderedDict([('x', 12), ('y', 5), ('z', 10)])
>>> dict(d)
{'x': 12, 'y': 5, 'z': 10}
>>>

这里看到Point.asdict() 返回的是OrderedDict类型,它需要通过dict() 来转换成字典类型。

Point.asdict() 的返回类型与Python的版本有关,在 3.1 版更改: 返回一个 OrderedDict 而不是 dict

在 3.8 版更改: 返回一个常规 dict 而不是 OrderedDict。 因为自 Python 3.7 起,常规字典已经保证有序。 如果需要 OrderedDict 的额外特性,推荐的解决方案是将结果转换为需要的类型: OrderedDict(nt._asdict())

  • Point._replace():改变元组的某个字段的值,因为元组默认是无法更改的,所以不能通过p1.x = 10 来修改它。
1
2
3
4
5
6
7
>>> p1.x = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

>>> p1._replace(x=20)
Point(x=20, y=5, z=8)
  • Point(**d):将一个字典转换成命名元组,需要使用** 操作符。
1
2
3
4
5
6
>>> d = {'x':12, 'y':15, 'z':10}
>>> d
{'x': 12, 'y': 15, 'z': 10}
>>> p3 = Point(**d)
>>> p3
Point(x=12, y=15, z=10)

2、deque

deque其实是 double-ended queue 的缩写,翻译过来就是双端队列,它最大的好处就是实现了从队列头部快速增加和取出对象。

你可能会说,原生的list也可以通过pop、insert取出和添加对象啊,但是list这两种方法的复杂度是O(n),而使用deque对象则是O(1)的复杂度,所以当你有队列的使用需求时,要记得使用deque。

双向队列(deque)对象支持以下方法:

  • append(x):添加 x 到右端。

  • appendleft(x):添加 x 到左端。

  • clear():移除所有元素,使其长度为0.

  • copy():创建一份浅拷贝。


参考链接

https://www.jb51.net/article/48771.htm

https://docs.python.org/zh-cn/3/library/collections.html#collections.namedtuple