Прямого доступа по индексу к элементам генератора в Python нет, но есть несколько способов получить элемент на определенной позиции.
Генераторы:
gen = (x for x in range(10, 20))
lst = list(gen)
print(lst[5]) # 15
Проблема: Требует создания списка со всеми элементами
from itertools import islice
gen = (x for x in range(1000000))
fifth_element = next(islice(gen, 5, None)) # Получаем 5-й элемент (индекс 5)
print(fifth_element) # 5
Преимущества:
gen = (x**2 for x in range(10))
index = 3
for i, item in enumerate(gen):
if i == index:
print(item) # 9
break
from more_itertools import nth
gen = (x for x in 'abcdef')
print(nth(gen, 3)) # 'd'
# Опасный пример с бесконечным генератором
inf_gen = (x for x in iter(int, 1))
# fifth = next(islice(inf_gen, 5, None)) # Бесконечный цикл!
Если нужен произвольный доступ, рассмотрите:
Пример с кешированием:
class IndexableGenerator:
def __init__(self, gen):
self.gen = gen
self.cache = []
def __getitem__(self, idx):
while len(self.cache) <= idx:
self.cache.append(next(self.gen))
return self.cache[idx]
gen = IndexableGenerator(x**2 for x in range(1000))
print(gen[5]) # 25
print(gen[3]) # 9 (из кеша)
Прямого доступа по индексу к генераторам нет, но можно:
itertools.islice
для эффективного получения элементаЛучший подход зависит от конкретной задачи:
islice
Генераторы лучше всего подходят для последовательной обработки, а не для произвольного доступа.