gpt4 book ai didi

Python 文档对 finally 中的 return 有误导性的解释

转载 作者:行者123 更新时间:2023-12-04 15:36:18 27 4
gpt4 key购买 nike

我正在阅读 python 文档以改进我的核心 python,我正在阅读有关 errors and exceptions 的内容

在文档中说

If a finally clause includes a return statement, the finally clause’s return statement will execute before, and instead of, the return statement in a try clause.

下面还提供了这个例子:

def bool_return():
try:
return True
finally:
return False

bool_return()

现在看这个例子,上面的陈述看起来很直接和公平,但是如果你稍微修改那个例子让它看起来像这样:

def bool_return():
try:
return print("foo")
finally:
return False

bool_return()

现在,如果你运行它,你会看到 foo将被打印并返回 False。现在文档说 finally 子句的返回将执行 before而不是 try 子句的 return 语句。如果是这样,那为什么我可以看到正在打印的 foo?

我用 pycharm 调试了这段代码,它显示首先执行 try 子句的 return 语句并打印字符串,然后输出 None由于 return 被退回语句,finally 子句中的 return 语句将在后面执行,这是程序的最后一次返回,因此函数覆盖了之前的 return 和 False被退回。

我的问题是:

1) 为什么文档说 finally 子句的 return 语句在 之前执行?

2) 为什么 doc 说执行 finally 子句的 return 语句而不是try 子句的 return 语句?

我相信这两种说法都与现实情况相反。

编辑:

阅读@iBug 的回答后很清楚 print("foo") 是如何实现的被评估但是None不返回。基本上,首先计算表达式,然后计算 return。发生。稍后return False in finally 被执行。这清楚地说明了为什么我们得到了我们所做的输出。

我仍然看到 return Falsereturn print("foo") 之后 终于执行了的尝试。

或者根据@iBug 的评论,10 RETURN_VALUE被完全绕过?

enter image description here

编辑

这个问题现在在文档中得到了解决,现在返回的内容是正确的。但是,如果您想知道“如何”,请阅读所有评论并仔细回答。

最佳答案

$ python3
Python 3.7.5 (default, Nov 20 2019, 09:21:52)
[GCC 9.2.1 20191008] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def bool_return():
... try:
... return print("foo")
... finally:
... return False
...
>>> import dis
>>> dis.dis(bool_return)
2 0 SETUP_FINALLY 8 (to 10)

3 2 LOAD_GLOBAL 0 (print)
4 LOAD_CONST 1 ('foo')
6 CALL_FUNCTION 1
8 RETURN_VALUE

5 >> 10 LOAD_CONST 2 (False)
12 RETURN_VALUE
>>>

正如您在上面看到的,return False 确实发生在 try block 中的 return 语句之前,但是在计算出要返回的值之后。

我认为文档可能意味着 return 语句 的“返回的 Action ”,或者换句话说,它没有考虑返回值的计算,这当然会发生在返回之前。


要观察8 RETURN_VALUE是否执行,可以在 Debug模式下编译CPython解释器,然后在GDB中运行。分步指南对于这个答案来说过于臃肿,所以我将在此处给出一个大纲 (Linux)。

  • 从官方来源(python.org 网站或 GitHub)获取 CPython 源代码
  • 配置调试构建 ./configure --with-pydebug(您可能还想提供 --prefix=/opt/python3-debug),makemake install
  • 在 GDB 中启动调试 Python:gdb/opt/python3-debug/bin/python3 和 (gdb) r
  • 照常定义函数 bool_return
  • Python/ceval.c 中找到字符串 RETURN_VALUE,记下行号 (for 3.8.1, it's 1911)。
  • 通过发送SIGTRAP挂起Python解释器,并在上一步的位置设置断点(b Python/ceval.c:1911),然后c
  • 观察断点到达两次,输出如下:
(gdb breakpoint info)
False
(gdb breakpoint info)
  • 观察您在 REPL 中输入的每个语句如何到达断点一次。这是为了了解到上面步骤中的第二个断点是由Python REPL引起的,所以只有第一个断点来自于函数中的一个return语句。

既然清楚了函数中只执行了一次return,那肯定是12 RETURN_VALUE,所以Python指令8 RETURN_VALUE 根本不执行。

关于Python 文档对 finally 中的 return 有误导性的解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59639733/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com