使用Return语句的奇怪的Try-Except-Else-Finally行为

Kyl*_*ens 77 python try-except

这是一些表现特殊的代码.这是我编写的行为的简化版本.这仍然会表现出奇怪的行为,并且我对于为什么会这样做有一些具体的问题.

我在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
Run Code Online (Sandbox Code Playgroud)

结果:

>>> print demo1()
3
>>> print demo2()
6
3
Run Code Online (Sandbox Code Playgroud)
  • 为什么demo 1返回3而不是1?
  • 为什么演示两次打印6而不是打印6 w/4或5?

Gar*_*tty 111

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

Python文档状态:

当在try ... finally语句的try套件中执行return,break或continue语句时,finally子句也会在"出路"中执行.continue语句中的continue语句是非法的.(原因是当前实施存在问题 - 将来可能会解除此限制).

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

  • 哦,我想我在最初的尝试中弄清楚它的返回导致它最终立即跳到外面 (5认同)
  • 为什么在第二个例子中不打印5?我认为这仍然没有得到很好的解释.返回的答案很好,但为什么第二个例子中的5不打印 (4认同)
  • 确切地说,因为`finally`阻止**总是**运行. (2认同)
  • 在演示二中,为什么它最终执行嵌套,最后踢到外面然后回到嵌套最终完成返回而不是简单地从外面返回None? (2认同)
  • 因为当调用 `return` 语句时,Python 会检查是否有任何需要执行的打开的 `finally` 子句(参见上面的引用)。 (2认同)

小智 6

执行顺序为:

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

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


yan*_*end 5

请注意, PEP601禁止在finally 子句中使用return 语句,但已被拒绝。然而,它已被添加到PEP8 的风格指南中,表明应避免使用它。