2016-12-25 63 views
3

代码

def gen(): 
    try: 
     for i in range(5): 
      yield i 
    except Exception as e: 
     print('Caught: ' + str(e)) 
    finally: 
     print('I am done') 

for x in gen(): 
    print(x) 
    if x == 2: 
     raise Exception('Catch me?') 

输出

0 
1 
2 
I am done 
Traceback (most recent call last): 
    File "test.py", line 13, in <module> 
    raise Exception('Catch me?') 
Exception: Catch me? 

问题条款

为什么代码执行finally条款而不是except条款?的Python:尝试...除了......终于在发电机

请给予解释与参考。

+1

你在'gen()'函数外面引发异常,所以它没有捕获它。并且'finally'总是被执行。 – furas

+1

因为'finally'每次执行时代码是否失败(它就像是一个清理),并且你在异常发生器之外引发了异常,所以它不知道它 – danidee

+0

尝试''g = gen() ; g.throw(ValueError)'''。 – wwii

回答

4

发电机功能的主体将只运行迭代的for循环。也就是说,for循环是指这样的:

  1. 从发电机获取下一个值
  2. 运行循环体
  3. 回到步骤1

只有步骤1涉及实际内运行的代码发电机功能。由于生成器函数中的try块内的代码不会引发任何异常,因此except子句没有任何可捕获的。子句执行finally,因为它总是执行(这就是finally的用途)。

在生成器上使用循环并不意味着整个循环体在生成器函数的“内部”运行。这意味着一次只能从发生器中获取一个值,直到耗尽。循环体仍然在自己的范围内执行,与生成器函数分开。

+0

因此,如果在具有'finally'子句的生成器之外引发异常,那么该子句何时运行?如果主函数使用多个生成器,每个生成器都有'finally'子句呢?他们按什么顺序执行? – Cyker

+1

@Cyker:如果这是你的问题,你应该编辑你的问题来问它。当'try'块中的代码结束时,会执行'finally'子句。如果你的发生器被挂在'try'块内,那么finally子句将不会被执行,直到发生器关闭(如果有的话)。 – BrenBarn