Skip to content

数据类型拓展

在内置数据类型(dict、list、set、tuple)的基础上,collections 模块还提供了几个额外的数据类型:
Counter、deque、defaultdict、namedtuple 和 OrderedDict 等。

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

Iterable

所有可以被for in循环的类型都是继承于Iterable

Python3.8 版本以上的问题

DeprecationWarning:

Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it willstop working

解决办法:
from collections import Iterable修改为from collections.abc import Iterable或者是使用typing里的别名

判断对象能被for in循环/或能使用高阶函数map/filter/reduce

shell
>>> from collections.abc import Iterable
>>> isinstance(123, Iterable)
False
>>> isinstance([1,23], Iterable)
True
>>> isinstance({1,2,3,}, Iterable)
True
>>> isinstance('123', Iterable)
True
>>> isinstance((123,), Iterable)
True
>>> isinstance((i for i in '123'), Iterable)
True

namedtuple

我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:

shell
>>> p = (1, 2)

但是,看到(1, 2),很难看出这个 tuple 是用来表示一个坐标的。
这时,namedtuple就派上了用场:

shell
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p.y
2
>>> p._asdict()
{'x': 1, 'y': 2}

类似的,如果要表示颜色,也可以用namedtuple定义:

python
color = namedtuple("color", ["R", "G", "B"])
yellow = color(255, 255, 0)

deque

使用 list 存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为 list 是线性存储,数据量大的时候,插入和删除效率很低。
deque 是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

python
from collections import deque

q = deque(["a", "b", "c"])
q.append("x")
q.appendleft("y")
q  # deque(['y', 'a', 'b', 'c', 'x'])

deque 除了实现 list 的append()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素。

OrderedDict

在低版本 python 中 dict 类型是数据结构 hashmap,其 key 是无序的
那时候在对 dict 做迭代时,我们无法确定 Key 的顺序。
如果要保持 Key 的顺序,可以用OrderedDict

shell
>>> from collections import OrderedDict
>>> od = OrderedDict()
>>> od['a'] = 1
>>> od['c'] = 2
>>> od['b'] = 3
>>> for k,v in od.items():
...     print(k,v)
...
a 1
c 2
b 3

OrderedDict的 Key 会按照插入的顺序排列(高版本 python 的 dict 也有这个特性了)

如果要按 key 字母排序:

python
OrderedDict(sorted(od.items(), key=lambda x: x[0]))

.move_to_end方法将 key 移动到最后

shell
>>> od.move_to_end('c')
>>> for k,v in od.items():
...     print(k,v)
...
a 1
b 3
c 2

defaultdict

实现了__miss__方法的 dict
使用dict时,如果引用的 Key 不存在,就会抛出KeyError
如果希望 key 不存在时,返回一个默认值,就可以用defaultdict

shell
>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1'] # key1存在
'abc'
>>> dd['key2'] # key2不存在,返回默认值
'N/A'

Counter

Counter 类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为 key,其计数作为 value。计数值可以是任意的 Interger(包括 0 和负数)。Counter 类和其他语言的 bags 或 multisets 很相似。

python
Counter("abcdeabcdabcaba")
# Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})