Я бы поспорил против соблазна обращаться с генераторами как со списками.Простой, но наивный подход - простая однострочная:
gen = (i for i in range(10))
list(gen)[3]
Но помните, что генераторы не похожи на списки.Они нигде не хранят свои промежуточные результаты, поэтому вы не можете вернуться назад.Я продемонстрирую проблему на простом примере в python repl:
>>> gen = (i for i in range(10))
>>> list(gen)[3]
3
>>> list(gen)[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Как только вы начнете проходить через генератор, чтобы получить n-е значение в последовательности, генератор теперь находится в другом состоянии, ипопытка получить n-е значение снова вернет вам другой результат, который может привести к ошибке в вашем коде.
Давайте рассмотрим другой пример, основанный на коде из вопроса.
Первоначально можно ожидать, что следующее напечатает 4
дважды.
gen = (i for i in range(10))
index = 4
for i, v in enumerate(gen):
if i == index:
answer = v
break
print(answer)
for i, v in enumerate(gen):
if i == index:
answer = v
break
print(answer)
, но напечатайте это в repl, и вы получите:
>>> gen = (i for i in range(10))
>>> index = 4
>>> for i, v in enumerate(gen):
... if i == index:
... answer = v
... break
...
>>> print(answer)
4
>>> for i, v in enumerate(gen):
... if i == index:
... answer = v
... break
...
>>> print(answer)
9
Удачи в поиске этой ошибкивниз.
РЕДАКТИРОВАТЬ:
Как указывалось, если генератор бесконечно долго, вы даже не можете преобразовать его в список.Выражение list(gen)
никогда не закончится.
Есть способ, которым вы можете поместить лениво оцененную оболочку кэширования вокруг бесконечного генератора, чтобы он выглядел как бесконечно длинный список, в который можно индексировать по желанию, но это заслуживаетсвой собственный вопрос и ответ, и будет иметь серьезные последствия для производительности.