题
我至少发现了以下行为 诡异的:
def errors():
try:
ErrorErrorError
finally:
return 10
print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined
使用时异常消失 return
里面一个 finally
条款。这是一个错误吗?这有记录在任何地方吗?
但真正的问题(以及我将标记为正确的答案)是:
python 开发人员允许这种奇怪行为的原因是什么?
解决方案
您问了一下Python开发者的推理。我不能替他们说话,但没有其他行为很有道理。函数可以返回一个值,也可以引发异常;它不能两者都做。一个“终于”条款的目的是提供一种是“保证”来运行,无论异常清理代码。通过把一个return语句中finally语句,你已经声明要返回值,无论什么时候,无论异常。如果Python的表现为你所问及引发的异常,这将是打破了“终于”条款的合同(因为它会失败,返回你告诉它返回的值)。
其他提示
当您使用
return
一个finally
子句中的异常消失。 ..是记载地方?
如果最后存在时,它指定一个“清除”处理程序。 try子句被执行,包括任何除了和其他条款。如果在任何条款发生异常,并没有被处理,除了被暂时保存。最终条款执行。如果有保存的例外,它是在最后条款的最终重新升起。 如果最终条款引发了另一个异常或执行了return或break语句,保存异常丢失。
以下是 Java/C#/Python/JavaScript 中finally 块中 return 的有趣比较:(存档链接)
从最后返回
就在今天,我正在帮助解决 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
, ,所以我假设,一个会被退回。但是,情况并非如此:我了解逻辑,最后必须执行部分,但是我对此感到不安。让我们看看 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()); } }
我更喜欢这种行为,最终子句中的控制流程无法混乱,因此它可以防止我们在脚上射击自己。只是为了完整,让我们检查其他语言的作用。
Python:
def a(): try: return 1 finally: return 2 print a()
JavaScript:
<script> function ReturnFromFinally() { try { return 1; } catch (e) { } finally { return 2; } } </script> <a onclick="alert(ReturnFromFinally());">Click here</a>
C ++和PHP中没有最终子句,因此我无法尝试使用编译器/解释器的最后两种语言。
我们的小实验很好地表明,C#具有解决这个问题的最佳方法,但是我很惊讶地得知所有其他语言都以相同的方式处理该问题。
从最后返回是的不强>一个好主意。我知道C#具体不允许对这样做。