回来吃异常

时间:2009-02-05 17:59:36

标签: python exception return finally

我发现以下行为至少怪异

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

print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined

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

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

4 个答案:

答案 0 :(得分:54)

  

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

It is:

  

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

答案 1 :(得分:35)

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

答案 2 :(得分:4)

这是一个有趣的比较,在finally块中返回,在Java / C#/ Python / JavaScript中: http://www.gettingclever.com/2008/07/return-from-finally.html

编辑:链接坏了。从https://web.archive.org/web/20120426091446/http://www.gettingclever.com/2008/07/return-from-finally.html复制:

  

从最后返回

     

就在今天,我正在帮助解决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());  
        }  
}  
     

我最初的猜测是,它应打印出1,我正在打电话   return,所以我假设一个人将被退回。但是,它不是   情况下:

     

the second return is executed

     

我理解逻辑,最后部分必须执行,但是   不知何故,我对此感到不安。让我们看看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());  
 }  
}  
     

error CS0157 Control cannot leave the body of a finally clause

     

我更喜欢这种行为,控制流程不能搞砸   在最后一句中,所以它阻止我们在自己身上射击   脚丫子。只是为了完整起见,让我们检查一下其他什么   语言呢。

     

的Python:

def a():  
 try:  
  return 1  
 finally:  
  return 2  
print a()  
     

Python returns 2 as well

     

JavaScript的:

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

JavaScript returns 2 as well

     

C ++和PHP中没有finally子句,所以我不能尝试最后一个   两种语言,我有编译器/解释器。

     

我们的小实验很好地表明,C#是最好的方法   对这个问题,但我很惊讶地了解到,所有的   其他语言以同样的方式处理问题。

答案 3 :(得分:3)

从最后回来是一个好主意。我知道C#特别禁止这样做。