[英]Why is reversing a list with slicing slower than reverse iterator
在 Python 中至少有两种方法可以反转列表,但迭代器方法要快得多(至少在 Python 2.7.x 中)。 我想了解导致这种速度差异的原因。
>>> x = range(1000)
>>> %timeit x[::-1]
100000 loops, best of 3: 2.99 us per loop
>>> %timeit reversed(x)
10000000 loops, best of 3: 169 ns per loop
我怀疑速度差异至少是由于以下原因:
reversed
是用 C 写的reversed
是一个迭代器,所以更少的内存开销我尝试使用dis
模块来更好地了解这些操作,但这并没有太大帮助。 我不得不将这些操作放在一个函数中来反汇编它们。
>> def reverselist(_list):
... return _list[::-1]
...
>>> dis.dis(reverselist)
2 0 LOAD_FAST 0 (_list)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 1 (-1)
12 BUILD_SLICE 3
15 BINARY_SUBSCR
16 RETURN_VALUE
>>> def reversed_iter(_list):
... return reversed(_list)
...
>>> dis.dis(reversed_iter)
2 0 LOAD_GLOBAL 0 (reversed)
3 LOAD_FAST 0 (_list)
6 CALL_FUNCTION 1
9 RETURN_VALUE
切片操作期间到底发生了什么,是否有大量内存开销? 也许切片是用纯 Python 实现的?
那是因为reversed
返回一个iterator
而切片返回一个完整的列表。
>>> lis = range(10)
>>> lis[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> reversed(lis)
<listreverseiterator object at 0x909dd0c>
您必须使用list()
将该迭代器转换为整个列表:
>>> lis = range(10**5)
>>> %timeit lis[::-1]
100 loops, best of 3: 2.8 ms per loop
>>> %timeit list(reversed(lis))
100 loops, best of 3: 3.13 ms per loop
reversed
帮助:
>>> reversed?
Type: type
String Form:<type 'reversed'>
Namespace: Python builtin
Docstring:
reversed(sequence) -> reverse iterator over values of the sequence
Return a reverse iterator
reversed()
返回一个迭代器。 它实际上并没有反转任何东西,直到你循环它。 从文档:
返回一个反向迭代器。
您需要比较将reversed()
的结果再次转换为列表所需的时间:
%timeit list(reversed(x))
只创建迭代器(它只是对原始列表的引用和初始化为列表长度的项目指针)根本不需要任何时间。
说完转身reversed()
返回到列表使得它慢了很多:
>>> import timeit
>>> x = range(1000)
>>> timeit.timeit('x[::-1]', 'from __main__ import x')
4.623600006103516
>>> timeit.timeit('list(reversed(x))', 'from __main__ import x')
16.647125005722046
reversed()
实际上并不反转任何东西,它只是返回一个对象,该对象可用于以相反的顺序迭代容器的元素。 这就是为什么它比实际反转元素更快。
请注意,您还有与切片运算符相同的reverse()
。
reverse()
原地运行。 切片运算符返回一个列表对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.