【问题标题】:try / else with return in try blocktry / else 在 try 块中返回
【发布时间】:2011-09-16 08:40:39
【问题描述】:

我在 python 中遇到了一个奇怪的行为。我在 python 帮助或 SE 中找不到有关此的信息,所以这里是:

def divide(x, y):
    print 'entering divide'
    try:
        return x/y
    except:
        print 'error'
    else:
        print 'no error'
    finally:
        print 'exit'

print divide(1, 1)
print divide(1, 0)

输出:

entering divide
exit
1
entering divide
error
exit
None

如果在try 中返回值,python 似乎不会进入else 块。但是,它将始终位于 finally 块中。我真的不明白为什么。有人可以帮我解决这个逻辑吗?

谢谢

【问题讨论】:

    标签: python exception-handling


    【解决方案1】:

    http://docs.python.org/reference/compound_stmts.html#the-try-statement

    可选的 else 子句在控制流出时执行 try 子句结束。

    目前,除了在 异常或执行 return、continue 或 break 语句。

    【讨论】:

    • 可惜没有else 等价物可以保证在未捕获异常时运行,即使引发了尝试returns 或未捕获的异常(这也会停止@ 987654324@从运行)
    【解决方案2】:

    这种行为的原因是因为try内部的return。

    发生异常时,finally 和 except 块都在 return 之前执行。否则只有finally 执行,else 不执行,因为函数已经返回。

    这按预期工作:

    def divide(x, y):
        print 'entering divide'
        result = 0
        try:
            result = x/y
        except:
            print 'error'
        else:
            print 'no error'
        finally:
            print 'exit'
    
        return result
    
    print divide(1, 1)
    print divide(1, 0)
    

    【讨论】:

      【解决方案3】:

      else 块未执行,因为您在函数有机会这样做之前就离开了。

      但是,finally 块始终会被执行(除非你拔掉电源线或类似的东西)。

      考虑一下(作为一个思想实验;请不要在实际代码中这样做):

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

      看看它返回了什么:

      >>> whoops()
      False
      

      如果您对此感到困惑,那么您并不孤单。某些语言(如 C#)会主动阻止您在 finally 子句中放置 return 语句。

      【讨论】:

      • +1 对 C# 的评论。我对 else 和 finally 之间的逻辑差异感到困惑。这似乎是一个困难的设计问题。
      • +1 用于突出显示可以设置返回值,比如说,两次!这在实际代码中肯定是个坏主意。无论如何,限制return 和raise 的数量总是一个好主意,因为要澄清代码输出。
      • 其实try的return也可以。发生的事情是try 的返回语句运行“之后”最终运行。这里@tim 在try 和finally 中首先使用了return 2 次。由于 try 的 return 在 finally 块之后执行,finally 已经有了自己的 return!所以finally's return 运行并且'原始'try's return 从来没有改变运行!哈,终于好强大了!
      【解决方案4】:

      为什么else 子句不运行?

      else 子句对于必须执行的代码很有用如果 try 子句没有引发异常。

      • 当您调用divide(1, 0) 时,您的try 子句会引发异常 ZeroDivisionError,因此else 子句不会运行。

      • 当您调用divide(1, 1) 时,try 子句成功运行,并返回。所以永远不会到达else 子句。


      为什么finally 子句总是运行?

      finally 子句总是在离开 try 语句之前执行,无论是否发生异常。

      见上文。


      参考https://docs.python.org/3.5/tutorial/errors.html

      【讨论】:

        【解决方案5】:

        "return" 结束函数并返回您希望它返回的任何内容。所以它当然不会继续。 “finally”总是被执行。

        【讨论】:

          猜你喜欢
          • 2017-07-20
          • 1970-01-01
          • 1970-01-01
          • 2012-05-18
          • 1970-01-01
          • 1970-01-01
          • 2016-05-06
          • 1970-01-01
          • 2010-10-25
          相关资源
          最近更新 更多