为什么Python的enumerate这么慢?

7 投票
2 回答
12467 浏览
提问于 2025-04-15 13:57

为什么“enumerate”比“xrange + lst[i]”慢呢?


>>> from timeit import Timer
>>> lst = [1,2,3,0,1,2]*1000
>>> setup = 'from __main__ import lst'
>>> s1 = """
for i in range(len(lst)):
    elem = lst[i]
"""
>>> s2 = """
for i in xrange(len(lst)):
    elem = lst[i]
"""
>>> s3 = """
for i, v in enumerate(lst):
    elem = v
"""
>>> t1 = Timer(s1, setup); t2 = Timer(s2, setup); t3 = Timer(s3, setup)
>>> t1.timeit(3000), t2.timeit(3000), t3.timeit(3000)
(1.9263118636586494, 1.6119261665937992, 1.9606022553145719)
>>> t1.timeit(3000), t2.timeit(3000), t3.timeit(3000)
(1.93520258859715, 1.6145745478824836, 1.9529405971988041)

编辑:我在想为什么

for i, v in enumerate(lst):
    elem = i, v
for i in xrange(len(lst)):
    elem = i, lst[i]
慢。

2 个回答

6

可能是因为你对 enumerate 做了一些限制。试试这个:

>>> s3 = """
for i, elem in enumerate(lst):
    pass
"""

更新 还有两个额外的理由,说明为什么在命令行中使用 timeit 是个好主意,Alex 没提到:

(1) 它会为你做“最佳中的 N 次”测试。
(2) 它会帮你计算出需要多少次循环才能得到有意义的结果。

19

如果你测量得当,你会发现其实没有什么区别(在这个例子中,enumerate比xrange快一点点,但这个差别小到几乎可以忽略不计):

$ python -mtimeit -s'lst=[1,2,3,0,1,2]*1000' 'for i in xrange(len(lst)): elem=lst[i]'
1000 loops, best of 3: 480 usec per loop
$ python -mtimeit -s'lst=[1,2,3,0,1,2]*1000' 'for i, elem in enumerate(lst): pass'
1000 loops, best of 3: 473 usec per loop

(顺便说一下,我总是建议在命令行中使用timeit来测量时间,而不是在代码里或者解释器提示符下使用,因为这样输出的结果格式很好,容易看,而且时间单位也很清楚)。

在你的代码中,使用enumerate的时候多了一步操作:你在for循环的头部把列表项赋值给了v,然后又把v赋值给了elem;而在xrange的情况下,你只把项赋值给elem一次。其实在我的例子中,无论是哪种情况,我也是只赋值一次,当然了;你为什么要多次赋值呢?!在循环体内,你对elemi的操作在这两种形式中是完全可以一样的,只是enumerate的情况多了一些冗余而已。

撰写回答