Может ли кто-нибудь объяснить разницу между этими двумя казнями? Вот моя функция генератора:
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
.