Я ожидал, что итерация в случае повторения нескольких циклов будет намного быстрее, чем использование генератора, а мой код предполагает, что это ложь.Скорость для повторения нескольких раз по генератору по сравнению со списком
Мое понимание (операцией я имею в виду любое выражение, определяющее элемент):
- список требует п операции для инициализации
- , но затем каждый цикл по списку только захват элемент из памяти
- , таким образом, м петли по списку требуют только n операции
- генератор не требует каких-либо операции для инициализации
- однако, цикл над генератором работает операции в лета
- , таким образом, один цикл над генератором требует п операции
- но м петли над генератором требуют NXM операции
И я проверил мои ожидания, используя следующий код:
from timeit import timeit
def pow2_list(n):
"""Return a list with powers of 2"""
results = []
for i in range(n):
results.append(2**i)
return results
def pow2_gen(n):
"""Generator of powers of 2"""
for i in range(n):
yield 2**i
def loop(iterator, n=1000):
"""Loop n times over iterable object"""
for _ in range(n):
for _ in iterator:
pass
l = pow2_list(1000) # point to a list
g = pow2_gen(1000) # point to a generator
time_list = \
timeit("loop(l)", setup="from __main__ import loop, l", number=10)
time_gen = \
timeit("loop(g)", setup="from __main__ import loop, g", number=10)
print("Loops over list took: ", time_list)
print("Loops over generator took: ", time_gen)
И результаты удивили меня ...
Loops over list took: 0.20484769299946493
Loops over generator took: 0.0019217690005461918
Каким-то образом с помощью генератора появляется гораздо быстрее, чем списки, даже когда цикл более 1000 раз. И в этом случае мы говорим о двух порядках! Зачем?
EDIT:
Спасибо за ответы. Теперь я вижу свою ошибку. Я ошибочно предположил, что генератор начинается с начала на новом цикле, как диапазон:
>>> x = range(10)
>>> sum(x)
45
>>> sum(x)
45
Но это было наивным (диапазон не является генератором ...).
Что касается возможного дублирующегося комментария: моя проблема связана с несколькими циклами по генератору, что не объясняется в другом потоке.
Ваше предположение, что генератор работает быстрее, неверен. Возможный дубликат работы [Generators vs List Comprehension в Python] (http://stackoverflow.com/questions/30112326/generators-vs-list-comprehension-performance-in-python) – AChampion
То, что разность скоростей на два порядка отличается должен предупредить вас о том, что с вашим тестом что-то не так. Попробуйте 'loop (pow_2_gen (1000))' для точного результата. – Dunes
Ваш тест, если он испорчен. Одна функция должна создать полный список в памяти, другой должен только возвращать итератор. Использование было @Dunes предложили получить более точные результаты. –