数据类型拓展
在内置数据类型(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
>>> 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
可以表示不变集合,例如,一个点的二维坐标就可以表示成:
>>> p = (1, 2)
但是,看到(1, 2),很难看出这个 tuple 是用来表示一个坐标的。
这时,namedtuple
就派上了用场:
>>> 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
定义:
color = namedtuple("color", ["R", "G", "B"])
yellow = color(255, 255, 0)
deque
使用 list 存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为 list 是线性存储,数据量大的时候,插入和删除效率很低。
deque 是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
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
:
>>> 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 字母排序:
OrderedDict(sorted(od.items(), key=lambda x: x[0]))
.move_to_end
方法将 key 移动到最后
>>> 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
:
>>> 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 很相似。
Counter("abcdeabcdabcaba")
# Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})