Что такое генераторpython-76

Генератор — это особый вид итератора, который позволяет лениво (по требованию) генерировать значения, не загружая их все в память сразу. Генераторы создаются с помощью функций с yield или генераторных выражений.

Основные особенности генераторов

  1. Ленивые вычисления (Lazy Evaluation) — значения вычисляются только при запросе
  2. Экономия памяти — не хранят всю последовательность в памяти
  3. Одноразовость — после полного прохода генератор истощается
  4. Сохранение состояния — запоминают место выполнения между вызовами

Два способа создания генераторов

1. Функции-генераторы

Используют ключевое слово yield вместо return:

def countdown(n):
    print("Starting countdown from", n)
    while n > 0:
        yield n  # Возвращает значение и приостанавливает выполнение
        n -= 1
    print("Countdown finished!")

# Использование:
for num in countdown(3):
    print(num)  # Выводит 3, 2, 1

2. Генераторные выражения

Похожи на list comprehensions, но используют круглые скобки:

squares = (x**2 for x in range(5))  # Генераторное выражение

print(next(squares))  # 0
print(next(squares))  # 1

Как работают генераторы?

  1. При вызове функции-генератора она возвращает объект-генератор (но не выполняет код сразу)
  2. При первом вызове next() выполнение идет до первого yield
  3. При следующем вызове next() выполнение продолжается с места остановки
  4. Когда функция завершается, генерируется StopIteration
def simple_gen():
    yield "first"
    yield "second"
    yield "third"

gen = simple_gen()
print(next(gen))  # "first"
print(next(gen))  # "second"
print(next(gen))  # "third"
print(next(gen))  # StopIteration

Преимущества генераторов

  1. Эффективность памяти — не нужно хранить всю последовательность
  2. Бесконечные последовательности — можно генерировать бесконечные потоки данных
  3. Конвейерная обработка — можно объединять несколько генераторов в цепочки
# Бесконечная последовательность
def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

# Конвейерная обработка
def pipeline(data):
    squared = (x**2 for x in data)
    negated = (-x for x in squared)
    return negated

Генераторы vs Итераторы

Характеристика Генераторы Итераторы
Синтаксис yield или генераторные выражения Реализация __next__
Сложность реализации Простая Более сложная
Состояние Сохраняется автоматически Нужно управлять вручную

Практические примеры использования

1. Чтение больших файлов

def read_large_file(file_path):
    with open(file_path) as f:
        for line in f:
            yield line.strip()

2. Генерация бесконечных последовательностей

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

3. Конвейеры обработки данных

def process_pipeline(data):
    # Каждый шаг обрабатывает элементы по одному
    validated = (x for x in data if x is not None)
    transformed = (transform(x) for x in validated)
    filtered = (x for x in transformed if x > 0)
    return filtered

Отправка данных в генератор

Генераторы могут не только выдавать значения, но и получать их через send():

def accumulator():
    total = 0
    while True:
        value = yield total
        if value is None:
            break
        total += value

gen = accumulator()
next(gen)  # Инициализация
print(gen.send(10))  # 10
print(gen.send(20))  # 30

Резюмируем

Генератор — это особый вид итератора, создаваемый с помощью функций с yield или генераторных выражений. Ключевые преимущества: ленивые вычисления, экономия памяти и простота создания бесконечных последовательностей. Генераторы идеально подходят для обработки потоков данных, работы с большими файлами и создания конвейеров обработки.