43

以下代码引发语法错误:

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

为什么子句continue中不允许有finally语句?

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

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

如果重要的话,我使用的是 Python 2.6.6。

4

7 回答 7

27

禁止在 finally 子句中使用continue,因为它的解释会有问题。如果由于异常而执行 finally 子句,你会怎么做?

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

我们可以决定这段代码应该做什么,也许会吞下异常;但良好的语言设计表明并非如此。如果代码让读者感到困惑,或者如果有更清晰的方式来表达预期的逻辑(可能使用try: ... except Exception: pass; continue),那么将其保留为SyntaxError会有一些优势。

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

于 2011-11-28T21:30:31.103 回答
6

Python 语言参考禁止continuefinally子句中使用。我不完全确定为什么。可能是因为continuetry子句内确保finally执行,并且决定在子句continue内应该做什么finally有点模棱两可。

编辑:@Mike Christensen 对该问题的评论指出了 Python 核心开发人员讨论这种构造的歧义的线程。此外,在使用 Python 九年多的时间里,我从未想过这样做,所以这可能是开发人员不想在上面花费太多时间的相对少见的情况。

于 2011-11-28T21:17:57.393 回答
5

由于实现存在问题,finally 子句中的 continue 语句是非法的。在 Python 3.8 中,这个限制被取消了。

该错误是issue32489 - Allow 'continue' in 'finally' 子句

修复的拉取请求:https ://github.com/python/cpython/pull/5822

于 2018-04-20T05:27:19.170 回答
2

我没有在另一个回复中看到它,但我认为在这种情况下你可能想要的是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只有在没有异常的情况下才会执行该块。所以这意味着:

  1. 我们print i
  2. 我们trydo_something_that_might_fail(i)
  3. 如果它抛出SomeExceptionprint i一次又一次地跌倒
  4. 否则,我们continue(并且i永远不会打印)
于 2011-11-29T19:55:08.570 回答
2

因为使用 a 而引发异常然后被吞掉的可能性是一个强有力的论据,但是当您使用or代替continue时,异常也会被吞掉。breakreturn

例如,这有效并且异常被吞没:

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

这再次没有错误(在函数中)并且异常也被吞没:

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

那么为什么在一个块中允许break并且被允许,不管有没有可能引发的错误,但不是?returnfinallycontinue

您还可以考虑问题中以下因素的组合:

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

这意味着在每个循环中,由于finally总是执行,你总是会有一个continue女巫基本上说“中止当前迭代”,“中止当前迭代”,“中止当前迭代”......女巫真的没有任何意义. break但是使用and也没有意义return。当前迭代也被中止,唯一的区别是您现在只得到一个迭代。

所以这个问题“为什么continue不允许在 a 中finally?” 也可以问为“为什么是breakreturn允许的?”。

也许是因为那时不这样做是有道理的?这是开发人员的决定,现在是这样吗?当然,这也可能是实现者的懒惰,但谁知道呢,也许他们有什么想法,也许在另一个版本的 Python 中,以另一种方式拥有它会更有意义?

这个想法是,这里的例子只是极端的。你不只是写那样的代码,对吗?块中肯定有一些逻辑finally来说明什么时候去break/return/continue,无论如何,而不是像那样直截了当。因此,恕我直言,应该允许continue在 a中使用,因为如果我需要的话,我会很感激使用in编写一个干净的代码,而不是针对这个限制诉诸代码解决方法(即在 Python 的哲学中“我们都是在这里同意的成年人” )。finallycontinuefinally

于 2011-11-30T21:50:09.490 回答
2

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

因此,您的代码...

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

这是更清洁和简洁。Python 不允许在 finally 块中继续,因为 continue 之后的所有代码将永远不会被执行。(稀疏优于密集。)

于 2011-11-29T02:02:21.877 回答
-1

现在这个功能在 3.8 版本中可用

https://docs.python.org/3/whatsnew/3.8.html

示例代码

def new_f():
    for i in range(0,24):
        try:
            print(1/0)
        except:
            print('In Exception')
        finally:
            print('In finally')
            continue
于 2019-10-19T12:11:10.237 回答