ENIGMA AI
ENIGMA AI

Какие методы есть у генератора в Python, которых нет у обычного итератора?

встречается 1× Python middle language_specific

Как ответить

У генераторов есть метод send(), throw() и close() — у обычных итераторов их нет. Разницу важно понимать на практике, особенно если работаешь с корутинами или управляешь потоком данных. Обычный итератор просто возвращает следующий элемент через __next__() или выбрасывает StopIteration. Генератор — это синтаксический сахар над итератором, но с дополнительными возможностями за счёт сохранения состояния и двусторонней связи.

send(value) — передаёт значение в генератор как результат последнего yield. Используется, например, для конфигурации поведения на лету. Допустим, у нас генератор, который копит строки, и через send мы указываем лимит:

def logger():
    limit = 10
    count = 0
    while count < limit:
        msg = yield
        print(f"Log: {msg}")
        count += 1

Первый вызов next() нужен, чтобы запустить генератор до первого yield. После этого gen.send("error") передаёт строку. Если бы это был обычный итератор, такой гибкости нет — он либо возвращает фиксированный элемент, либо перебирает коллекцию.

throw(type, value, traceback) — бросает исключение в точку yield. Генератор может перехватить его и продолжить или завершиться. Используется, когда нужно прервать или переключить режим работы внешней обработки. Пример: если генератор обрабатывает запросы, а мы хотим закрыть соединение, шлём GeneratorExit через close(). close() — это фактически throw(GeneratorExit), который гарантированно завершает генератор. Обычный итератор просто прекращает итерацию, но не обрабатывает внешние сигналы.

Ещё есть момент с атрибутами gi_frame и gi_running — они тоже специфичны для генераторов и помогают отследить состояние (выполняется ли сейчас, есть ли фрейм). В CPython это реализовано через структуру PyGenObject.

На практике я редко пользуюсь send и throw в продакшене — чаще их используют для кооперативной многозадачности (например, в asyncio до async/await). Но если нужно передать контекст внутрь генератора, то send — единственный чистый способ без внешнего состояния.

Ключевые тезисы

  • Генератор поддерживает send(value) для двусторонней связи, throw(exc) для бросания исключения и close() для принудительного завершения.
  • Обычный итератор реализует только __next__() и не может принимать данные или обрабатывать исключения.
  • Первый вызов next() обязателен перед send(), иначе будет TypeError.
  • close() реализован через throw(GeneratorExit) и очищает ресурсы (finally).

Что спросят дальше

  • — Как поведёт себя генератор, если внутри есть try-finally, и мы вызываем close()?
  • — Почему в корутинах sentinel (например, None) часто используют для проверки первого вызова?
  • — Работает ли send() с yield from? Как именно?

Готовьтесь к собеседованию с ENIGMA AI

AI-суфлёр подсказывает ответы прямо на собеседовании в реальном времени — незаметно для интервьюера.

Скачать приложение