Мы все знаем, что общий способ выполнения оператора определенное количество раз в 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
, так как оба являются генераторами. Это потому, что значение никогда не меняется?