106

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

我在 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
  • 为什么演示一返回 3 而不是 1?
  • 为什么演示 2 打印 6 而不是打印 6 w/4 或 5?
4

3 回答 3

143

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

Python 文档状态:

当在 try…finally 语句的 try 套件中执行 return、break 或 continue 语句时,finally 子句也会在“退出时”执行。</p>

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

这意味着当您尝试返回时,将finally调用该块,返回它的值,而不是您本来拥有的值。

于 2012-06-22T21:09:04.977 回答
9

执行顺序为:

  1. try block all 正常完成 -> finally block -> 函数结束
  2. try 块运行并进入异常 A -> finally 块 -> 函数结束
  3. try 块生成返回值并调用 return -> finally 块 -> 弹出返回值 -> 函数结束

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

于 2015-05-31T12:05:40.473 回答
2

请注意,已经有PEP601禁止从 finally 子句中返回语句,但它已被拒绝。然而,它已被添加到PEP8的样式指南中,应该避免使用它。

于 2021-01-29T12:35:56.837 回答