Python 为什么使用切片反转列表比反转迭代器慢

Python 为什么使用切片反转列表比反转迭代器慢,python,Python,在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 我怀

在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
    返回一个列表,而切片返回一个完整的列表

    >>> lis = range(10)
    >>> lis[::-1]
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    >>> reversed(lis)
    <listreverseiterator object at 0x909dd0c>
    
    帮助打开
    反向

    >>> reversed?
    Type:       type
    String Form:<type 'reversed'>
    Namespace:  Python builtin
    Docstring:
    reversed(sequence) -> reverse iterator over values of the sequence
    
    Return a reverse iterator
    
    >>反向?
    类型:类型
    字符串形式:
    名称空间:Python内置
    文档字符串:
    反向(序列)->序列值上的反向迭代器
    返回一个反向迭代器
    
    reversed()
    返回迭代器。它实际上不会反转任何东西,直到你在它上面循环。从:

    返回一个反向

    您需要比较将
    reversed()
    的结果再次转换为列表所需的时间:

    %timeit list(reversed(x))
    
    只创建迭代器(它只是对原始列表的引用和初始化为列表长度的项指针)根本不需要任何时间

    必须将
    reversed()
    返回到列表中会使速度慢很多:

    reversed()
    实际上并不反转任何内容,它只返回一个对象,该对象可用于按相反顺序遍历容器的元素。这就是为什么它比实际反转元素更快的原因

    请注意,还有与切片操作符相同的
    reverse()


    reverse()
    操作到位。切片操作符返回一个列表对象。

    很抱歉,我没有提到主题,但是在哪个python版本中,
    可以提供帮助?天哪,这似乎很明显,显然对我来说还为时过早。谢谢你的解释@septi
    在Ipython shell中,而不是Python的特定版本。@septi它是Ipython shell。不确定我怎么会错过这个。谢谢你的解释。顺便说一句,我不必为了使用
    dis
    模块而将这些操作放到方法中。有一个很好的
    lambda
    ,首先编译代码字符串(必需),然后将其传递到
    dis.dis
    list.reverse()
    操作到位,而不是
    反向
    %timeit list(reversed(x))
    
    >>> 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