collections.deque:为什么q[9999]比q[-1]快?
collections.deque: why q[9999] is faster than q[-1]?
如果我是编写此功能的程序员,我会将其实现为负值表示从右开始,正值表示从左开始,这将导致 q[-1] 比 q[9999] 快得多。
但是-1向右转1步似乎并不比9999向右转1步耗时,那么为什么q[-1]比q[9999]慢呢?
谢谢
>>> q = collections.deque()
>>> q.extend(range(10000))
>>> %timeit q[-1]
50.7 ns ± 0.195 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
>>> %timeit q[9999]
40.5 ns ± 0.528 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
如果您在 Python 中实现 __getitem__
,您将收到调用者使用的任何索引,无需修改。
然而,under the hood, collections.deque
implements the C API sequence protocol 和 __getitem__
的 C API 序列协议版本的工作方式不同。如果您传入负数,Python 会将序列的 len
添加到您的索引,然后再将其传递给 deque
的项目检索实现。
对于q[-1]
和q[9999]
,双端队列接收到的索引是9999
,它必须决定是从左边迭代还是从右边迭代来找到你想要的元素要求。但是,q[-1]
首先有一层额外的开销。
如果我是编写此功能的程序员,我会将其实现为负值表示从右开始,正值表示从左开始,这将导致 q[-1] 比 q[9999] 快得多。
但是-1向右转1步似乎并不比9999向右转1步耗时,那么为什么q[-1]比q[9999]慢呢?
谢谢
>>> q = collections.deque()
>>> q.extend(range(10000))
>>> %timeit q[-1]
50.7 ns ± 0.195 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
>>> %timeit q[9999]
40.5 ns ± 0.528 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
如果您在 Python 中实现 __getitem__
,您将收到调用者使用的任何索引,无需修改。
然而,under the hood, collections.deque
implements the C API sequence protocol 和 __getitem__
的 C API 序列协议版本的工作方式不同。如果您传入负数,Python 会将序列的 len
添加到您的索引,然后再将其传递给 deque
的项目检索实现。
对于q[-1]
和q[9999]
,双端队列接收到的索引是9999
,它必须决定是从左边迭代还是从右边迭代来找到你想要的元素要求。但是,q[-1]
首先有一层额外的开销。