使用切片语法与collections.deque

69 投票
6 回答
31539 浏览
提问于 2025-04-16 23:36

你想从下面的 deque 中高效、优雅且符合 Python 风格地提取第 3 到第 6 项,但又不想改变原来的内容:

from collections import deque
q = deque('',maxlen=10)
for i in range(10,20):
    q.append(i)

而且 切片语法 似乎在 deque 上不太好使...

6 个回答

10

这个问题虽然老旧,但对于未来的读者,Python的文档明确推荐使用 rotate 方法来处理这个问题:

rotate() 方法提供了一种实现双端队列(deque)切片和删除的方式。

https://docs.python.org/2/library/collections.html

这个方法的实现相对简单:

def slice_deque(d, start, stop, step):
    d.rotate(-start)
    slice = list(itertools.islice(d, 0, stop-start, step))
    d.rotate(start)
    return slice

它的效果和直接使用 islice 是一样的,不过 rotate 在跳到起始点时更高效。另一方面,它也会暂时改变双端队列,这可能会引发线程安全的问题。

10

我更喜欢这个,因为它更简短,所以更容易阅读:

output = list(q)[3:6+1]
99
import itertools
output = list(itertools.islice(q, 3, 7))

比如说:

>>> import collections, itertools
>>> q = collections.deque(xrange(10, 20))
>>> q
deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
>>> list(itertools.islice(q, 3, 7))
[13, 14, 15, 16]

这个方法应该比之前发布的其他解决方案更有效率。有什么证据吗?

[me@home]$ SETUP="import itertools,collections; q=collections.deque(xrange(1000000))"

[me@home]$ python -m timeit  "$SETUP" "list(itertools.islice(q, 10000, 20000))"
10 loops, best of 3: 68 msec per loop

[me@home]$ python -m timeit "$SETUP" "[q[i] for i in  xrange(10000, 20000)]"
10 loops, best of 3: 98.4 msec per loop

[me@home]$ python -m timeit "$SETUP" "list(q)[10000:20000]"
10 loops, best of 3: 107 msec per loop

撰写回答