Может ли кто-нибудь объяснить разницу между этими двумя казнями? Вот моя функция генератора:
def g(n):
try:
yield n
print("first")
except BaseException as e:
print(f"exception {e}")
raise e
finally:
print("second")
Когда я выполняю:
>>> a = next(g(2))
exception
second
Может ли кто-нибудь объяснить, почему a = next(g(2)) вызывает исключение и в чем разница с выполнением ниже?
>>> x = g(2)
>>> next(x)
2
Я ожидал, что когда я выполню a = next(g(2)), функция g(2) вернет генератор, а next() вернет первый выход генератора, но, видимо, возникнет исключение. Почему это происходит?






В первом сценарии генератор собирает мусор после next(), наконец срабатывает и вызывает исключение. Во втором генератор удерживается x, предотвращая это и позволяя нормально работать.
Редактировать:
Исключение GeneratorExit выдается, когда генератор закрывается, после чего будет выполнен блокfinally.
Также из документов:
Если генератор не возобновится до его завершения (по достижении нулевого счетчика ссылок или при сборке мусора), будет вызван метод
close()генератора-итератора, позволяющий выполнить любые ожидающие предложенияfinally.
Почему же это вызывает исключение?
@JoanRàfols Я отредактировал свой ответ.
Также см. этот ответ, в котором описана та же проблема и объясняется, почему возникает вопрос GeneratorExit.
Я думаю, что это может быть правильно. Во втором примере, если вы следуете за
next(x)сx = None, вы увидитеexceptionиsecond.