В Python есть два основных способа объявления генераторов:
Самый распространенный способ — создать функцию с использованием ключевого слова yield
. При вызове такая функция возвращает объект-генератор.
def my_generator():
yield 1
yield 2
yield 3
# Использование:
gen = my_generator() # Возвращает генератор, не выполняя код
print(next(gen)) # 1
print(next(gen)) # 2
Особенности:
yield
yield
Аналог list comprehension, но с круглыми скобками, который создает генератор.
gen_exp = (x**2 for x in range(5)) # Генераторное выражение
print(next(gen_exp)) # 0
print(next(gen_exp)) # 1
Особенности:
Хотя это менее распространено, можно создать генератор как класс:
class MyGenerator:
def __init__(self, limit):
self.limit = limit
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.limit:
self.current += 1
return self.current
raise StopIteration
gen = MyGenerator(3)
print(next(gen)) # 1
print(next(gen)) # 2
Для делегирования другому генератору:
def delegated_gen():
yield from range(3)
yield from 'abc'
gen = delegated_gen()
print(list(gen)) # [0, 1, 2, 'a', 'b', 'c']
def read_file_lines(filename):
with open(filename) as f:
for line in f:
yield line.strip()
def infinite_counter(start=0):
while True:
yield start
start += 1
def even_numbers(limit):
for num in range(limit):
if num % 2 == 0:
yield num
next()
запускает выполнение до первого yield
StopIteration
def demo_gen():
print("Начало")
yield 1
print("Продолжение")
yield 2
print("Конец")
gen = demo_gen()
next(gen) # Начало \n 1
next(gen) # Продолжение \n 2
next(gen) # Конец \n StopIteration
В Python генераторы можно объявить:
yield
(наиболее распространенный способ)(x for x in iterable)
yield from
для делегированияГенераторы предоставляют мощный инструмент для ленивых вычислений, эффективной работы с памятью и создания сложных итерационных паттернов.