回来吃异常

nos*_*klo 26 python return exception finally

我发现以下行为至少很奇怪:

def errors():
    try:
        ErrorErrorError
    finally:
        return 10

print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined
Run Code Online (Sandbox Code Playgroud)

returnfinally子句中使用时,异常消失.那是一个错误吗?有记录吗?

但真正的问题(以及我将标记为正确的答案)是:
python开发人员允许这种奇怪行为的理由是什么?

Sil*_*ost 53

returnfinally子句中使用时,异常消失...有记录吗?

它是:

如果finally存在,则指定'cleanup'处理程序.执行try子句,包括任何except和else子句.如果任何子句中发生异常但未处理,则会临时保存该异常.finally子句被执行.如果存在已保存的异常,则会在finally子句的末尾重新引发异常.如果finally子句引发另一个异常或执行return或break语句,则保存的异常将丢失.


Car*_*yer 35

您询问了Python开发人员的推理.我不能代表他们,但没有其他行为是有道理的.函数可以返回一个值,也可以引发异常; 它不能两者兼顾."finally"子句的目的是提供"保证"运行的清理代码,无论例外情况如何.通过在finally子句中放置一个return语句,您已经声明要返回一个值,无论如何,无论异常如何.如果Python表现得像你要求并引发了异常,它将破坏"finally"子句的契约(因为它将无法返回你告诉它返回的值).

  • 合理的行为:从`finally`静态地禁止`return`.我们看到它令人困惑. (6认同)

JV.*_*JV. 5

这是finally 块中返回的有趣比较,其中包括 - Java/C#/Python/JavaScript:(存档链接

从最后返回

就在今天,我正在帮助解决 Java 中的一些错误,并遇到了有趣的问题 - 如果在 try/catch 语句中使用 return 会发生什么?最后部分是否应该启动?我将问题简化为以下代码片段:

下面的代码打印出什么?

class ReturnFromFinally {  
 public static int a() {  
  try {  
   return 1;  
  }  
  catch (Exception e) {}  
  finally{  
   return 2;  
  }  
 }  

        public static void main(String[] args) {  
  System.out.println(a());  
        }  
}  
Run Code Online (Sandbox Code Playgroud)

我最初的猜测是,它应该打印出来1,我正在打电话 return,所以我假设,会被返回。然而,事实并非如此:

第二次返回执行

我理解逻辑,最后部分必须执行,但不知怎的,我对此感到不安。让我们看看 C# 在这种情况下做了什么:

class ReturnFromFinally  
{  
 public static int a()  
 {  
  try {  
          return 1;  
  }  
  catch (System.Exception e) {}  
  finally   
  {   
   return 2;  
  }  
 }  

 public static void Main(string[] args)  
 {  
  System.Console.WriteLine(a());  
 }  
}  
Run Code Online (Sandbox Code Playgroud)

错误CS0157控制不能离开finally子句的主体

我更喜欢这种行为,控制流不能在finally子句中被搞乱,所以它可以防止我们搬起石头砸自己的脚。为了完整起见,让我们检查一下其他语言是做什么的。

Python:

def a():  
 try:  
  return 1  
 finally:  
  return 2  
print a()  
Run Code Online (Sandbox Code Playgroud)

Python 也返回 2

JavaScript:

<script>  
function ReturnFromFinally()  
{  
 try  
 {  
  return 1;  
 }  
 catch (e)  
 {  
 }  
 finally  
 {  
  return 2;  
 }  
}  
</script>  
<a onclick="alert(ReturnFromFinally());">Click here</a>  
Run Code Online (Sandbox Code Playgroud)

JavaScript 也返回 2

C++ 和 PHP 中没有 finally 子句,因此我无法尝试我拥有编译器/解释器的最后两种语言。

我们的小实验很好地表明,C# 对于这个问题有最好的方法,但我很惊讶地发现,所有其他语言都以相同的方式处理这个问题。

  • 这并不奇怪。所有语言都做唯一明智的事情(尊重finally子句),除了C#,这可以防止搬起石头砸自己的脚。这不符合 Python 的精神,Python_总是_给你所有你需要的绳子来上吊自己:-)“我们都是同意的成年人。” (3认同)