带有Return语句的奇怪的Try-Except-Else-Finally行为


88

这是一些行为特殊的代码。这是我编写的行为的简化版本。这仍然会显示出奇怪的行为,我对为什么会发生这种情况有一些具体的疑问。

我在Windows 7上使用Python 2.6.6。

def demo1():
    try:
        raise RuntimeError,"To Force Issue"
    except:
        return 1
    else:
        return 2
    finally:
        return 3

def demo2():
    try:
        try:
            raise RuntimeError,"To Force Issue"
        except:
            return 1
        else:
            return 2
        finally:
            return 3
    except:
        print 4
    else:
        print 5
    finally:
        print 6

结果:

>>> print demo1()
3
>>> print demo2()
6
3
  • 为什么演示1返回3而不是1?
  • 为什么演示两次打印6而不是打印带有4或5的6?

Answers:


123

因为保证可以执行finally语句(因此,假定没有断电或Python无法控制的任何事情)。这意味着在函数可以返回之前,它必须运行finally块,该块返回不同的值。

Python文档状态:

当在try…finally语句的try套件中执行return,break或Continue语句时,finally子句也将在“出路”上执行。

函数的返回值由最后执行的return语句确定。由于finally子句始终执行,因此在finally子句中执行的return语句将始终是最后执行的语句:

这意味着,当您尝试返回时,将finally调用该块,并返回其值,而不是原来的值。


4
为什么在第二个示例中不打印5?我认为这还不能很好地解释。返回的答案很好,但是为什么第二个示例中的5不打印
Joran Beasley 2012年

5
哦,我想我理解了它在最初尝试的回报使其立即终于跳到外
Joran比斯利

2
正是因为finally总是在运行。
加雷斯·拉蒂

2
在演示二中,为什么它最终执行嵌套,最后踢向外部,然后最后返回嵌套以完成返回,而不是最终简单地从外部返回None?
凯尔·欧文斯

1
因为在return调用该语句时,Python会检查是否finally需要执行任何打开的子句(请参见上面的引用)。
Gareth Latty

6

执行顺序为:

  1. 尝试阻止所有正常完成->最终阻止->函数结束
  2. 尝试运行块并进入异常A->最终阻塞->函数结束
  3. 尝试块返回值并调用返回->最终阻止->弹出返回值->函数结束

因此,finally块中的任何返回都将提前结束步骤。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.