目录
一、绪论
collections 作为 Python 的内建集合模块,实现了许多十分高效的特殊容器数据类型,即除了 Python 通用内置容器: dict、list、set 和 tuple 等的替代方案。在 IDLE 输入 help(collections) 可查看帮助文档,其中常见的类/函数如下:
名称 | 功能 |
namedtuple | 用于创建具有命名字段的 tuple 子类的 factory 函数 (具名元组) |
deque | 类似 list 的容器,两端都能实现快速 append 和 pop (双端队列) |
ChainMap | 类似 dict 的类,用于创建多个映射的单视图 |
Counter | 用于计算 hashable 对象的 dict 子类 (可哈希对象计数) |
OrderedDict | 记住元素添加顺序的 dict 子类 (有序字典) |
defaultdict | dict 子类调用 factory 函数来提供缺失值 |
UserDict | 包装 dict 对象以便于 dict 的子类化 |
UserList | 包装 list 对象以便于 list 的子类化 |
UserString | 包装 string 对象以便于 string 的子类化 |
而本文详述的对象为双端队列 —— deque 类对象。
二、deque 类
2.1 简介
collections.deque([iterable[, maxlen]])
Deque 是 ”double-ended-queue” 的缩写 (发音是 “deck”),意为 双端队列。输入 可迭代对象 iterable 并返回一个新的双端队列对象。若不指定可迭代对象 iterable,则返回的双端队列对象为空。
Deque 可以从队列 两端添加 (append) 和 弹出 (pop) 元素,且两个方向的 时间复杂度均为 O(1) 。虽然 list 对象也支持类似操作,但 list 在开头插入 insert(0, item) 或弹出 (pop(0)) 元素的时间复杂度均为 O(n)。
若可选参数 maxlen 未指定或为 None,deque 将成为 任意长度 的双端队列。否则, maxlen 就是 限定最大长度,将构造一个固定大小的双端队列。当 deque 元素已满且有新元素从一端“入队”时,数量相同的旧元素将从另一端“出队” (被移除)。
2.2 方法速查表
形式 | 说明 |
append(x) | 从 deque 最右端加入元素 x |
appendleft(x) | 从 deuqe 最左端加入元素 x |
extend(iterable) | 使用可迭代对象 iterbale 中的元素扩展 deque 右端 |
extendleft(iterable) | 使用可迭代对象 iterbale 中的元素扩展 deque 左端 |
insert(i, x) | 在 index=i 的位置插入元素 x (若导致 deque 长度超过 maxlen,引发 IndexError) |
pop() | 弹出 deque 最右端的一个元素 (若无元素引发 IndexError) |
popleft() | 弹出 deque 最左端的一个元素 (若无元素引发 IndexError) |
remove(x) | 移除从左到右找到的第一个 x (若无 x 引发 ValueError) |
clear() | 清空 deque 中的所有元素,使之为空 deque (长度归0) |
copy() | 创建一份当前 deque 的浅拷贝 |
count(x) | 计算 deque 中 x 的个数 |
index(x[, start[, stop]]) | 返回在 [start, stop] 之间从左到右找到的第一个 x 的 index (未找到引发 ValueError) |
reverse() | 将当前 deque 逆序排列,返回 None |
rotate(n=1) | n 为正数向右循环移动 n 步,n 为负数向左循环移动 n 步,若 deque 非空, 向右循环移动 1 步等价于 d.appendleft(d.pop()) 向左循环移动 1 步等价于 d.append(d.popleft()) |
此外,deque 还支持索引、迭代、清洗 以及 len(d)、reversed(d)、copy.copy(d)、copy.deepcopy(d) 等内建函数通用操作,支持用 in 成员测试操作符。deque 两端的索引增、删、改复杂度是 O(1),在中间的复杂度则比 O(n) 略低。从 Python 3.5 开始 deque 还支持 __add__()、__mul__()、__imul__() 等。
2.3 用法示例
2.3.1 新建对象
首先,导入 collections 模块中的 deque:
>>> from collections import deque
创建一个 deque 对象:
>>> d = deque() # 创建空 deque
>>> d
deque([])
注意,可迭代对象 iterable 包括:序列 sequence (list、string、tuple)、set、dict、迭代器 iterator、生成器 generator、文件对象 等。可以将 可迭代对象 iterable 转换为 双端队列对象 deque,例如:
>>> d1 = deque([1, 2, 3, 4]) # list → deque
>>> d1
deque([1, 2, 3, 4])
# -----------------------------------------------------------------------
>>> d2 = deque({1, 2, 3, 4}) # set → deque
>>> d2
deque([1, 2, 3, 4])
# -----------------------------------------------------------------------
>>> d3 = deque({'a':1, 'b':2}) # dict → deque
>>> d3
deque(['a', 'b'])
# -----------------------------------------------------------------------
>>> d4 = deque(range(1, 5)) # iterable → deque
>>> d4
deque([1, 2, 3, 4])
2.3.2 元素操作
新建一个 deque 对象用于说明:
>>> d0 = deque([1, 2, 3, 4, 5])
>>> d0
deque([1, 2, 3, 4, 5])
两端添加元素:
>>> d0.append(6)
>>> d0
deque([1, 2, 3, 4, 5, 6])
# -----------------------------------------------------------------------
>>> d0.appendleft(-1)
>>> d0
deque([-1, 1, 2, 3, 4, 5, 6])
用可迭代对象 iterable 拓展两端元素:
>>> d0.extend([7, 8])
>>> d0
deque([-1, 1, 2, 3, 4, 5, 6, 7, 8])
# -----------------------------------------------------------------------
>>> d0.extendleft([-3, -2])
>>> d0
deque([-2, -3, -1, 1, 2, 3, 4, 5, 6, 7, 8]) # 看到没, 按元素逐个 extend 而非之间拼接上去
任意位置 (index) 插入元素:
>>> d0.insert(0, -4) # index=0
>>> d0
deque([-4, -2, -3, -1, 1, 2, 3, 4, 5, 6, 7, 8])
>>> d0.insert(12, 9) # index=12
>>> d0
deque([-4, -2, -3, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9])
两端弹出元素:
>>> d0.pop()
9
>>> d0
deque([-4, -2, -3, -1, 1, 2, 3, 4, 5, 6, 7, 8])
>>> d0.popleft()
-4
>>> d0
deque([-2, -3, -1, 1, 2, 3, 4, 5, 6, 7, 8])
移除从左到右找到的首个指定元素:
>>> d0.remove(-3)
>>> d0
deque([-2, -1, 1, 2, 3, 4, 5, 6, 7, 8])
浅拷贝:(注意,此处未体现浅拷贝的根本含义,点击学习)
>>> dcp = d0.copy()
>>> dcp
deque([-2, -1, 1, 2, 3, 4, 5, 6, 7, 8])
指定元素计数:
>>> d0.count(6)
1
返回从左到右找到的首个指定元素的位置 index:
>>> d0.index(6)
7
逆序排列:
>>> d0.reverse()
>>> d0
deque([8, 7, 6, 5, 4, 3, 2, 1, -1, -2])
元素双向循环移动指定步数:
>>> d0.rotate(2) # 右循环移动 2 步
>>> d0
deque([-1, -2, 8, 7, 6, 5, 4, 3, 2, 1])
>>> d0.rotate(-2) # 左循环移动 2 步
>>> d0
deque([8, 7, 6, 5, 4, 3, 2, 1, -1, -2])
清空 deque:
>>> d0.clear()
>>> d0 # 清空
deque([])
>>> dcp # 浅拷贝外围元素健在
deque([-2, -1, 1, 2, 3, 4, 5, 6, 7, 8])
参考文献:
《Python Immediate》