为什么Python的enumerate这么慢?
为什么“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
一次。其实在我的例子中,无论是哪种情况,我也是只赋值一次,当然了;你为什么要多次赋值呢?!在循环体内,你对elem
和i
的操作在这两种形式中是完全可以一样的,只是enumerate的情况多了一些冗余而已。