deque.popleft()比list.pop(0)更快,这是因为deque已被优化以在O(1)中执行popleft(),而list.pop(0)需要O(n)(请参阅deque对象) 。
_collectionsmodule.c中用于deque的注释和代码以及listobject.c中用于list的注释和代码提供了实现见解,以解释性能差异。即,双端队列对象“由双向链接列表组成”,可以有效地优化两端的追加和弹出,而列表对象甚至不是单链接列表,而是C数组(指向元素的指针)(请参阅Python2.7 listobject。h#l22和Python3.5listobject.h#l23),这使其非常适合元素的快速随机访问,但在移除第一个元素之后需要O(n)时间来重新放置所有元素。
对于Python 2.7和3.5,这些源代码文件的URL为:
https://hg.python.org/cpython/file/2.7/Modules/_collectionsmodule.c
https://hg.python.org/cpython/file/2.7/Objects/listobject.c
https://hg.python.org/cpython/file/3.5/Modules/_collectionsmodule.c
https://hg.python.org/cpython/file/3.5/Objects/listobject.c
使用%timeit,当双端队列和列表具有相同的52个元素时,deque.popleft()和list.pop(0)之间的性能差异约为4倍,而当长度为10** 8。测试结果如下。
import stringfrom collections import deque%timeit d = deque(string.letters); d.popleft()1000000 loops, best of 3: 1.46 µs per loop%timeit d = deque(string.letters)1000000 loops, best of 3: 1.4 µs per loop%timeit l = list(string.letters); l.pop(0)1000000 loops, best of 3: 1.47 µs per loop%timeit l = list(string.letters);1000000 loops, best of 3: 1.22 µs per loopd = deque(range(100000000))%timeit d.popleft()10000000 loops, best of 3: 90.5 ns per loopl = range(100000000)%timeit l.pop(0)10 loops, best of 3: 93.4 ms per loop解决方法
deque.popleft()并且list.pop(0)似乎返回相同的结果。它们之间有什么性能差异,为什么?