【问题标题】:Reverse the list while creation创建时反转列表
【发布时间】:2017-01-29 17:45:24
【问题描述】:

我有这个代码:

def iterate_through_list_1(arr):
    lala = None
    for i in range(len(arr))[::-1]:
        lala = i

def iterate_through_list_2(arr):
    lala = None
    for i in range(len(arr), 0, -1):
        lala = i

从逻辑上讲,以相反的顺序遍历range() 创建的列表应该比使用range() 创建列表并随后使用[::-1] 反转它更有效。但是 cProfile 告诉我,iterate_through_list_1 函数运行得更快。

我使用了 python-3。在这里您可以看到两个相同数组的分析输出,其中包含 100000000 个元素。

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   1    5.029    5.029    5.029    5.029    bs.py:24(iterate_throgh_list_2)
   1    4.842    4.842    4.842    4.842    bs.py:19(iterate_throgh_list_1)

在创建列表时,Python 切片下面发生了什么?

【问题讨论】:

  • Python 2.x 还是 3.x?数字是多少,时间差是多少?你是怎么测试的?您是否对其进行了多次迭代?
  • 第二个功能非常更加明显。除非有 大量 优势,否则更喜欢它 - 并且它会对您的应用程序产生影响。
  • @MartinBonner 如果这很完美,那for obj in reversed(arr) 呢?或者,如果您真的需要指标,for idx, obj in enumerate(reversed(arr))?
  • @ŁukaszRogalski,感谢您改进我的问题。我添加了更多描述
  • @ŁukaszRogalski:确实,这两个看起来都更好,尽管枚举版本将返回索引在反向列表中,所以它会变成 0,1,2 ( not 2, 1 0) 用于三元素列表。

标签: python performance list memory


【解决方案1】:

精心设计的测试表明,第一个函数在 Python 2.x 上最慢(主要是因为必须创建两个列表,第一个作为递增范围,第二个作为恢复的第一个)。我还包含一个使用reversed 的演示。

from __future__ import print_function
import sys
import timeit

def iterate_through_list_1(arr):
    lala = None
    for i in range(len(arr))[::-1]:
        lala = i

def iterate_through_list_2(arr):
    lala = None
    for i in range(len(arr), 0, -1):
        lala = i

def correct_iterate_reversed(arr):
    lala = None
    for obj in reversed(arr):
        lala = obj


print(sys.version)
print('iterate_through_list_1', timeit.timeit('iterate_through_list_1(seq)',
                                              setup='from __main__ import iterate_through_list_1\nseq = range(0, 10000)',
                                              number=10000))
print('iterate_through_list_2', timeit.timeit('iterate_through_list_2(seq)',
                                              setup='from __main__ import iterate_through_list_2\nseq = range(0, 10000)',
                                              number=10000))
print('correct_iterate_reversed', timeit.timeit('correct_iterate_reversed(seq)',
                                                setup='from __main__ import correct_iterate_reversed\nseq = range(0, 10000)',
                                                number=10000))

结果:

2.7.12 (default, Jun 29 2016, 14:05:02) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)]
iterate_through_list_1 3.87919592857
iterate_through_list_2 3.38339591026
correct_iterate_reversed 2.78083491325

3.x 中的差异都可以忽略不计,因为在每种情况下迭代的对象都是惰性的。

3.5.2 (default, Jul 28 2016, 21:28:00) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)]
iterate_through_list_1 2.986786328998278
iterate_through_list_2 2.9836046030031866
correct_iterate_reversed 2.9411962590020266

【讨论】:

    猜你喜欢
    • 2020-09-20
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    相关资源
    最近更新 更多