обеспечить вызов end() в функции g()

Поместите yield в try/finally и вызывайте end() в finally. Это обеспечивает очистку при исчерпании или закрытии начатого генератора, но не гарантирует мгновенное закрытие брошенного генератора.

Короткий ответ

Что ответить на собеседовании

Поместите yield в try/finally и вызывайте end() в finally. Это обеспечивает очистку при исчерпании или закрытии начатого генератора, но не гарантирует мгновенное закрытие брошенного генератора.

Подробный разбор

Ответ с пояснениями

Условие

обеспечить вызов end() в функции g()

не модифицировать функции, кроме g()

def begin(): ...

def end(): ...

def g(): begin() yield 1 yield 2 end()

def f(): a = g() return next(a)

def ff(): for item in g(): ...

Ответ

Поместите yield в try/finally и вызывайте end() в finally. Это обеспечивает очистку при исчерпании или закрытии начатого генератора, но не гарантирует мгновенное закрытие брошенного генератора.

Изменение только g:

def g():
    begin()
    try:
        yield 1
        yield 2
    finally:
        end()

При полном обходе ff блок завершится естественно. В f генератор теряет последнюю локальную ссылку; CPython обычно сразу финализирует его, но язык не гарантирует такой момент сборки во всех реализациях и при циклах ссылок.

Строгая гарантия освобождения при досрочном выходе требует close() или contextlib.closing у потребителя. Если менять потребителей запрещено, эту границу решения нужно прямо обозначить. Незапущенный генератор ещё не вызывал begin.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее