为什么在Python中的finally子句中不允许继续?

以下代码引发了一个语法错误:

>>> for i in range(10): ... print i ... try: ... pass ... finally: ... continue ... print i ... File "<stdin>", line 6 SyntaxError: 'continue' not supported inside 'finally' clause 

为什么在finally一个条款中不允许使用continue语句?

PS另一方面,这个其他的代码没有问题:

 >>> for i in range(10): ... print i ... try: ... pass ... finally: ... break ... 0 

如果有关系,我使用Python 2.6.6。

禁止在最后条款中继续使用,因为它的解释是有问题的。 如果finally子句由于exception而被执行,你会怎么做?

 for i in range(10): print i try: raise RuntimeError finally: continue # if the loop continues, what would happen to the exception? print i 

我们可以做出这个代码应该做什么的决定,也许吞噬这个exception。 但是良好的语言devise却不然。 如果代码混淆了读者,或者如果有更明确的方式来expression逻辑意思(或许用try: ... except Exception: pass; continue ),那么留下这个作为SyntaxError是有好处的。

有趣的是,你可以在finally子句中放入一个return ,它将吞下所有的exception,包括KeyboardInterruptSystemExitMemoryError 。 这可能不是一个好主意;-)

Python语言参考禁止在finally子句中使用continue 。 我不完全确定为什么。 也许是因为在try子句中continue确保finally被执行,并且在finally子句中决定continue应该做些什么有些含糊。

编辑:@Mike Christensen对这个问题的评论指出了Python核心开发人员讨论这个构造模糊的问题。 另外,在使用Python九年多的时间里,我从来不想这样做,所以开发人员不需要花费太多时间,这可能是一种相对不常见的情况。

我认为这个原因其实很简单。 finally关键字之后的continue语句每次都执行。 这是最后声明的本质。 您的代码是否引发exception是无关紧要的。 最后会被执行。

因此,你的代码…

 for i in range(10): print i try: pass finally: continue print i # this (and anything else below the continue) won't ever be executed! 

相当于这个代码…

 for i in range(10: print i try: pass finally: pass 

这是更清洁和terser。 Python不允许在finally块中继续,因为continue之后的所有代码都不会执行。 (稀疏比密集好。)

我没有看到在另一个回应中提到,但我认为你可能想在这种情况下是try..else

 for i in range(10): print i try: #pass <= I commented this out! do_something_that_might_fail(i) except SomeException: pass else: continue print i 

else块只有在没有exception的情况下才会执行。 那么这意味着什么呢?

  1. 我们print i
  2. 我们try do_something_that_might_fail(i)
  3. 如果抛出SomeException ,则通过并再次print i
  4. 否则,我们continuei从来没有打印)

提出exception,然后因为使用continue被吞下的可能性是一个强有力的论据,但是当你使用breakreturn时,exception也会被吞噬。

例如,这是有效的,吞噬例外:

 for i in range(10): print i try: raise Exception finally: break print i # not gonna happen 

这再次工作没有错误(当在一个函数中),exception也被吞噬:

 for i in range(10): print i try: raise Exception finally: return print i # not gonna happen 

那么为什么会在finally一个块中允许breakreturn ,不pipe有没有可能引发的错误,而是continue呢?

您可能还会考虑以下因素的组合:

  • finally总是执行;
  • continue “中止”当前的迭代。

这将意味着在每一个循环内部,由于finally总是执行,你总是会有一个continue女巫基本上说“中止当前迭代”,“中止当前迭代”,“中止当前迭代”…女巫并不真正使任何意义。 但是使用breakreturn也没有意义。 当前的迭代也被中止,唯一的区别是你现在只需要一次迭代。

所以这个问题“为什么finally不允许呢?” 也可以被问为“为什么breakreturn允许?”。

也许是因为这个意义上没有意义? 这是开发者的决定,现在它是这样吗? 当然,这也可能是实现者的懒惰,但是谁知道,也许他们有一些想法,也许在另一个版本的Python中,用另一种方式更有意义呢?

这个想法是, 这里的例子是极端的 。 你不只是写这样的代码,是吗? 不pipe怎么说,在finally块里肯定会有一些逻辑来说明什么时候break/return/continue ,而不仅仅是这样。 因此,恕我直言, continue在一个finally应该被允许,因为我会感激写一个干净的代码,使用finally continue ,如果这是我所需要的,而不是诉诸于这种限制的代码解决方法(即在Python的哲学“我们都是同意在这里的成年人“)。