2011-11-28 31 views
36

下面的代码引发一个语法错误:为什么在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声明?

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

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

如果它很重要,我使用Python 2.6.6。

+2

看起来只是纯粹的懒惰? http://www.gossamer-threads.com/lists/python/dev/484210 –

+0

@Mike Christensen:我也发现这个线程,但是文档说“继续可能只会出现在语法上嵌套在for或while循环中,但不会嵌套在函数或类定义**或该循环中的finally子句**中。那么这是懒惰还是故意的,后来需要改变? ...像Python中的很多东西... – ElenaT

+0

你读过整个线程吗? - 有一些有趣的信息可以说明它会在finally块中“继续”,以及可能出现的各种问题。值得阅读。 –

回答

24

在finally子句中使用继续是禁止的,因为它的解释会有问题。如果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有一些优势。

有趣的是,你可以把一个一个最终子句中,它会吞下所有的异常,包括一个KeyboardInterruptSystemExit的MemoryError。这可能不是一个好主意;-)

+4

我同意。如果异常中断了你的程序,那么finally子句的用法通常是用来结束松散的结束。对于“最后继续”(在英语中也是无意义的),如果存在影响循环条件本身的问题,将会有重复异常的风险,直到循环终止,甚至无限重复。 – paislee

+2

在finally块中继续可以按照与返回或加注相同的方式进行处理。在这个例子中,异常将被吞下并且循环将继续。 –

+2

我认为人们忘记了'finally'块中的代码总是被执行。 – jathanism

6

finally子句中的Python语言参考forbids the use of continue。我不完全确定为什么。也许是因为在try子句中的continue确保finally被执行,并且在finally子句中决定什么continue应该有点含糊不清。

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

+0

似乎是一个很好的解释给我。 'finally'和'continue'的组合肯定是值得重构的东西。 – jsalonen

+2

在这些情况下,有时候最好不要让开发人员去做某些事情 - 否则你必须规范,解决和解决允许这种事情的决定产生的任何古怪。 –

3

我认为这样做的原因其实很简单。 finally关键字之后的continue语句每次都执行。这是最后声明的本质。你的代码是否抛出异常是无关紧要的。最后会被执行。

因此,你的代码...

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之后的所有代码都不会执行。 (稀疏比密集好。)

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. 如果它抛出SomeException,砸锅和print i再次
  4. 否则,我们continue(和i从不打印)
2

获得例外的可能性,然后只是吞下,因为哟我使用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 

那么,为什么breakreturn被允许在finally块中,有无可能引发的错误,但是continue不是?

您也可以考虑在发行的以下几个因素的结合:

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

这将意味着每个循环中,因为finally始终执行,你将永远有一个continue女巫基本上 说:“放弃当前迭代”,“中止当前迭代”,“中止当前迭代” ..女巫没有任何意义。但是使用breakreturn也没有意义。当前的迭代也会中止,唯一的差异是 ,您现在只需要一次迭代即可完成。

所以问题“为什么continue不允许在finally?”也可以被问为“为什么允许breakreturn?”。

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

想法是,这里的例子只是极端的。你不只是写这样的代码,是吗?无论如何,在finally块中肯定会有一些 逻辑来说明何时break/return/continue,而不仅仅是这样。因此,应该允许在finally之内的恕我直言continue,因为如果这是我所需要的,我将不用诉诸于代码解决方法来解决此限制(例如,在Python的哲学中“我们都是同意这里的成年人“)。

+1

我对这个讨论有点迟,但'finally'子句中的'continue'语句并不一定意味着每一次迭代都会被中止,因为你可以将'continue'语句包装在一个条件语句中。 (这仍然是一个SyntaxError。) – Fraxtil

相关问题