python:deque 对象
- deque 用法
class collections.deque([iterable[, maxlen]])
返回一个新的双向队列对象,从左到右初始化(用方法 append()) ,从 iterable (迭代对象) 数据创建。如果 iterable 没有指定,新队列为空。
Deque队列是由栈或者queue队列生成的(发音是 “deck”,”double-ended queue”的简称)。Deque 支持线程安全,内存高效添加(append)和弹出(pop),从两端都可以,两个方向的大概开销都是 O(1) 复杂度。
虽然 list 对象也支持类似操作,不过这里优化了定长操作和 pop(0) 和 insert(0, v) 的开销。它们引起 O(n) 内存移动的操作,改变底层数据表达的大小和位置。
如果 maxlen 没有指定或者是 None ,deques 可以增长到任意长度。否则,deque就限定到指定最大长度。一旦限定长度的deque满了,当新项加入时,同样数量的项就从另一端弹出。限定长度deque提供类似Unix filter tail 的功能。它们同样可以用与追踪最近的交换和其他数据池活动。
双向队列(deque)对象支持以下方法:
append(x)
添加 x 到右端。
appendleft(x)
添加 x 到左端。
clear()
移除所有元素,使其长度为0.
copy()
创建一份浅拷贝。
3.5 新版功能.
count(x)
计算 deque 中元素等于 x 的个数。
3.2 新版功能.
extend(iterable)
扩展deque的右侧,通过添加iterable参数中的元素。
extendleft(iterable)
扩展deque的左侧,通过添加iterable参数中的元素。注意,左添加时,在结果中iterable参数中的顺序将被反过来添加。
index(x[, start[, stop]])
返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。 返回第一个匹配项,如果未找到则引发 ValueError。
3.5 新版功能.
insert(i, x)
在位置 i 插入 x 。
如果插入会导致一个限长 deque 超出长度 maxlen 的话,就引发一个 IndexError。
3.5 新版功能.
pop()
移去并且返回一个元素,deque 最右侧的那一个。 如果没有元素的话,就引发一个 IndexError。
popleft()
移去并且返回一个元素,deque 最左侧的那一个。 如果没有元素的话,就引发 IndexError。
remove(value)
移除找到的第一个 value。 如果没有的话就引发 ValueError。
reverse()
将deque逆序排列。返回 None 。
3.2 新版功能.
rotate(n=1)
向右循环移动 n 步。 如果 n 是负数,就向左循环。
如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。
Deque对象同样提供了一个只读属性:
maxlen
Deque的最大尺寸,如果没有限定的话就是 None 。
3.1 新版功能.
除了以上操作,deque 还支持迭代、封存、len(d)、reversed(d)、copy.copy(d)、copy.deepcopy(d)、成员检测运算符 in 以及下标引用例如通过 d[0] 访问首个元素等。 索引访问在两端的复杂度均为 O(1) 但在中间则会低至 O(n)。 如需快速随机访问,请改用列表。
Deque从版本3.5开始支持 add(), mul(), 和 imul() 。
示例:
>>>
from collections import deque
d = deque('ghi') # make a new deque with three items
for elem in d: # iterate over the deque's elements
print(elem.upper())
G
H
I
d.append('j') # add a new entry to the right side
d.appendleft('f') # add a new entry to the left side
d # show the representation of the deque
deque(['f', 'g', 'h', 'i', 'j'])
d.pop() # return and remove the rightmost item
'j'
d.popleft() # return and remove the leftmost item
'f'
list(d) # list the contents of the deque
['g', 'h', 'i']
d[0] # peek at leftmost item
'g'
d[-1] # peek at rightmost item
'i'
list(reversed(d)) # list the contents of a deque in reverse
['i', 'h', 'g']
'h' in d # search the deque
True
d.extend('jkl') # add multiple elements at once
d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
d.rotate(1) # right rotation
d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
d.rotate(-1) # left rotation
d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
deque(reversed(d)) # make a new deque in reverse order
deque(['l', 'k', 'j', 'i', 'h', 'g'])
d.clear() # empty the deque
d.pop() # cannot pop from an empty deque
Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
d.pop()
IndexError: pop from an empty deque
d.extendleft('abc') # extendleft() reverses the input order
d
deque(['c', 'b', 'a'])
deque 用法
这一节展示了deque的多种用法。
限长deque提供了类似Unix tail 过滤功能
def tail(filename, n=10):
'Return the last n lines of a file'
with open(filename) as f:
return deque(f, n)
另一个用法是维护一个近期添加元素的序列,通过从右边添加和从左边弹出
def moving_average(iterable, n=3):
# moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
# https://en.wikipedia.org/wiki/Moving_average
it = iter(iterable)
d = deque(itertools.islice(it, n-1))
d.appendleft(0)
s = sum(d)
for elem in it:
s += elem - d.popleft()
d.append(elem)
yield s / n
一个 轮询调度器 可以通过在 deque 中放入迭代器来实现。值从当前迭代器的位置0被取出并暂存(yield)。 如果这个迭代器消耗完毕,就用 popleft() 将其从对列中移去;否则,就通过 rotate() 将它移到队列的末尾
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
iterators = deque(map(iter, iterables))
while iterators:
try:
while True:
yield next(iterators[0])
iterators.rotate(-1)
except StopIteration:
# Remove an exhausted iterator.
iterators.popleft()
rotate() 方法提供了一种方式来实现 deque 切片和删除。 例如, 一个纯的Python del d[n] 实现依赖于 rotate() 来定位要弹出的元素
def delete_nth(d, n):
d.rotate(-n)
d.popleft()
d.rotate(n)
要实现 deque 切片, 使用一个类似的方法,应用 rotate() 将目标元素放到左边。通过 popleft() 移去老的条目(entries),通过 extend() 添加新的条目, 然后反向 rotate。这个方法可以最小代价实现命令式的栈操作,诸如 dup, drop, swap, over, pick, rot, 和 roll 。