我们都知道在Python中执行某个语句多次的常见方法是使用
for
循环。一般的做法是:# I am assuming iterated list is redundant.
# Just the number of execution matters.
for _ in range(count):
pass
我相信没有人会争论上面的代码是常见的实现方式,但还有另一种选择。通过Python列表创建的速度,通过引用相乘来实现。
# Uncommon way.
for _ in [0] * count:
pass
还有旧的while
方法。
i = 0
while i < count:
i += 1
我测试了这些方法的执行时间。下面是代码。
import timeit
repeat = 10
total = 10
setup = """
count = 100000
"""
test1 = """
for _ in range(count):
pass
"""
test2 = """
for _ in [0] * count:
pass
"""
test3 = """
i = 0
while i < count:
i += 1
"""
print(min(timeit.Timer(test1, setup=setup).repeat(repeat, total)))
print(min(timeit.Timer(test2, setup=setup).repeat(repeat, total)))
print(min(timeit.Timer(test3, setup=setup).repeat(repeat, total)))
# Results
0.02238852552017738
0.011760978361696095
0.06971727824807639
如果差异很小,我不会引入这个话题,但是可以看出速度的差异为100%。如果第二种方法更有效,为什么Python不鼓励这样的用法?是否有更好的方法?
测试是在Windows 10和Python 3.6下进行的。
根据@Tim Peters的建议,
.
.
.
test4 = """
for _ in itertools.repeat(None, count):
pass
"""
print(min(timeit.Timer(test1, setup=setup).repeat(repeat, total)))
print(min(timeit.Timer(test2, setup=setup).repeat(repeat, total)))
print(min(timeit.Timer(test3, setup=setup).repeat(repeat, total)))
print(min(timeit.Timer(test4, setup=setup).repeat(repeat, total)))
# Gives
0.02306803115612352
0.013021619340942758
0.06400113461638746
0.008105080015739174
这提供了一种更好的方式,这基本上回答了我的问题。
为什么这比range
更快,因为两者都是生成器。是因为值从不改变吗?
for _ in itertools.repeat(None, count)
。意思是使用Python标准库中的itertools
模块来重复迭代None
对象count
次。循环中的下划线在Python中通常用作占位符来表示不关心的值。因此,这行代码的目的是为了重复执行某些操作count
次而已。 - Tim Peters