ale*_*123 -1 python exception generator
def gen():
try:
yield 1
yield 2
except:
print('hi')
def func():
for x in gen():
return x
print(func())
Run Code Online (Sandbox Code Playgroud)
此代码打印hi然后打印1。为什么它不直接打印1?提出了什么例外?
您func从生成器中检索第一个元素gen。之后,func有一个return声明。结果,func执行终止,导致gen生成器也退出。close当调用生成器的方法时,它会引发一个GeneratorExit异常,这就是本例中捕获的异常。这就是它打印的原因hi。之后,程序继续;func返回1并且该值被打印在代码的最后一行中。
该generator.close方法被调用是因为生成器死亡。循环之后for,不再有对生成器对象的剩余引用。如果将生成器分配给变量a = gen()并且没有完全消耗其迭代,则可以GeneratorExit通过直接调用a.close()或使用 终止对象来触发 的引发del a。
另一方面,如果您允许生成器完成其执行,它将不会引发GeneratorExit。当循环for _ in gen(): pass完成时,它成功结束生成器的执行gen,从而产生StopIteration由循环处理的异常for。但它不会提高GeneratorExit,因为在close调用时,执行gen已经结束。
有趣的是,它GeneratorExit不是继承自Exception而是继承自BaseException。如果你写except Exception: print('hi'),只会1被打印。这样,您可以管理生成器中引发的任何异常,而无需中断其执行:
def gen():
for i in (1, 2):
try:
yield i
except Exception:
pass
Run Code Online (Sandbox Code Playgroud)
如果您要使用except: pass它,它将捕获GeneratorExit并允许执行gen继续产生另一个值。根据generator.close文档,这不应该发生:
如果生成器产生一个值,则 a
RuntimeError被提升。
事实上,你会遇到RuntimeError:生成器忽略 GeneratorExit