Что такое подгенераторpython-83

Подгенератор — это генератор, который делегирует часть своей работы другому генератору с помощью синтаксиса yield from. Это мощная возможность Python, появившаяся в PEP 380.

Основная концепция

Подгенератор позволяет:

  1. Делегировать выполнение другому генератору
  2. Упрощать композицию генераторов
  3. Обрабатывать вложенные генераторы более элегантно

Синтаксис yield from

def delegator_gen():
    # Основной генератор
    yield from subgenerator()  # Делегирование подгенератору
    yield 'local value'

def subgenerator():
    # Подгенератор
    yield 1
    yield 2

gen = delegator_gen()
print(list(gen))  # [1, 2, 'local value']

Ключевые особенности подгенераторов

  1. Двусторонняя коммуникация:

    • Значения отправляются в делегирующий генератор
    • Исключения передаются в подгенератор
    • Возвращаемое значение подгенератора становится значением выражения yield from
  2. Автоматическая обработка StopIteration:

    • При завершении подгенератора выполнение продолжается в основном генераторе
  3. Вложенность:

    • Подгенераторы могут сами делегировать другим подгенераторам

Практические примеры

1. Обход вложенных структур

def flatten(nested):
    for sublist in nested:
        yield from sublist  # Делегирование для каждого подсписка

nested = [[1, 2], [3, 4], [5]]
print(list(flatten(nested)))  # [1, 2, 3, 4, 5]

2. Цепочки обработки данных

def process_pipeline(data):
    # Первый этап обработки
    cleaned = (x for x in data if x is not None)

    # Делегирование второму этапу
    yield from transform_data(cleaned)

def transform_data(items):
    for item in items:
        yield item * 2

data = [1, None, 2, 3]
print(list(process_pipeline(data)))  # [2, 4, 6]

3. Возврат значения из подгенератора

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

def gatherer():
    while True:
        # Получаем результат работы подгенератора
        res = yield from accumulator()
        yield f'Total: {res}'

gen = gatherer()
next(gen)  # Инициализация
gen.send(10)  # Отправляем значения
gen.send(20)
print(gen.send(None))  # 'Total: 30'

Преимущества использования подгенераторов

  1. Упрощение кода — избавление от вложенных циклов
  2. Разделение ответственности — каждый генератор выполняет свою задачу
  3. Эффективность — минимальные накладные расходы
  4. Гибкость — возможность построения сложных конвейеров обработки

Под капотом

Когда выполняется yield from:

  1. Делегирующий генератор приостанавливается
  2. Подгенератор получает управление
  3. Все send(), throw(), close() передаются подгенератору
  4. Когда подгенератор завершается, выполнение продолжается в основном генераторе

Резюмируем

Подгенератор — это генератор, которому делегируется часть работы через yield from. Основные преимущества:

  • Упрощение работы с вложенными генераторами
  • Двусторонний обмен данными между генераторами
  • Чистый и читаемый код для сложных итерационных задач
  • Эффективная композиция генераторов

Использование подгенераторов особенно полезно при обработке древовидных структур, построении конвейеров данных и реализации сложных конечных автоматов.