We all know that the common way of executing a statement a certain number of times in Python is to use a for
loop.
The general way of doing this is,
# I am assuming iterated list is redundant.
# Just the number of execution matters.
for _ in range(count):
pass
I believe nobody will argue that the code above is the common implementation, however there is another option. Using the speed of Python list creation by multiplying references.
# Uncommon way.
for _ in [0] * count:
pass
There is also the old while
way.
i = 0
while i < count:
i += 1
I tested the execution times of these approaches. Here is the code.
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
I would not initiate the subject if there was a small difference, however it can be seen that the difference of speed is 100%. Why does not Python encourage such usage if the second method is much more efficient? Is there a better way?
The test is done with Windows 10 and Python 3.6.
Following @Tim Peters' suggestion,
.
.
.
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
Which offers a much better way, and this pretty much answers my question.
Why is this faster than range
, since both are generators. Is it because the value never changes?