【问题标题】:Python try finally block returns [duplicate]Python尝试最终阻止返回[重复]
【发布时间】:2013-11-17 07:27:23
【问题描述】:

下面有有趣的代码:

def func1():
    try:
        return 1
    finally:
        return 2

def func2():
    try:
        raise ValueError()
    except:
        return 1
    finally:
        return 3

func1()
func2()

请有人解释一下,这两个函数会返回什么结果并解释原因,即描述执行顺序

【问题讨论】:

  • 你永远不需要有人来解释结果会是什么——你可以试试看。寻求理性是另一回事。

标签: python try-except try-finally


【解决方案1】:

来自 Python documentation

finally 子句总是在离开 try 语句之前执行,无论是否发生异常。当 try 子句中发生异常并且没有被 except 子句处理(或者它已经发生在 except 或 else 子句中)时,它会在 finally 子句执行后重新引发。当 try 语句的任何其他子句通过 break、continue 或 return 语句离开时,finally 子句也会在“退出时”执行。一个更复杂的示例(从 Python 2.5 开始,在同一 try 语句中具有 except 和 finally 子句):

因此,一旦使用 return 离开 try/except 块,这会将返回值设置为给定 - finally 块将 始终 执行,并且应该用于释放资源等,同时使用另一个返回 - 覆盖原来的。

在您的特定情况下,func1() 返回 2func2() 返回 3,因为这些是 finally 块中返回的值。

【讨论】:

  • 请注明出处
  • @thefourtheye 添加了文档文档的链接
  • 可能值得注意的是,给定示例,如果您不在finally 块中放置return,那么return 语句中的任何值在try 块中事实上,将被返回(并且不会被 None 覆盖)。
【解决方案2】:

它将始终转到finally 块,因此它将忽略tryexcept 中的return。如果您在tryexcept 上方有一个return,它将返回该值。

def func1():
    try:
        return 1 # ignoring the return
    finally:
        return 2 # returns this return

def func2():
    try:
        raise ValueError()
    except:
        # is going to this exception block, but ignores the return because it needs to go to the finally
        return 1
    finally:
        return 3

def func3():
    return 0 # finds a return here, before the try except and finally block, so it will use this return 
    try:
        raise ValueError()
    except:
        return 1
    finally:
        return 3


func1() # returns 2
func2() # returns 3
func3() # returns 0

【讨论】:

  • 它实际上并没有“忽略”它,而是“覆盖”它,对吗?也就是说,如果有 finally unless finally also 返回,则返回不会被忽略。而且,在尝试之前返回会使尝试无法访问,对吗?
  • 我已经测试过了,你完全正确。
【解决方案3】:

事先输入print 声明真的非常有帮助:

def func1():
    try:
        print 'try statement in func1. after this return 1'
        return 1
    finally:
        print 'after the try statement in func1, return 2'
        return 2

def func2():
    try:
        print 'raise a value error'
        raise ValueError()
    except:
        print 'an error has been raised! return 1!'
        return 1
    finally:
        print 'okay after all that let\'s return 3'
        return 3

print func1()
print func2()

这会返回:

try statement in func1. after this return 1
after the try statement in func1, return 2
2
raise a value error
an error has been raised! return 1!
okay after all that let's return 3
3

您会注意到,python 总是返回最后一个要返回的东西,而不管两个函数中的代码“到达”return 1

finally始终运行,因此函数中返回的最后一件事就是 finally 块中返回的内容。在func1 中,这是 2。在 func2 中,这是 3。

【讨论】:

  • You'll notice that python always returns the last thing to be returned, regardless that the code "reached" return 1 in both functions 我会说,当 python 在代码中找到一个 finally 块时,它会覆盖以前的返回值,我并不是说你上面的语句是错误的,但是我想说的是在 finally 块执行后转移控制权,从而在 finally 块中覆盖最终返回值。
【解决方案4】:

func1() 返回 2。func2() 返回 3。

finally 块不管异常还是最终都会执行。

您可以使用调试器查看执行顺序。例如,请参阅a screencast

【讨论】:

    猜你喜欢
    • 2017-11-05
    • 1970-01-01
    • 2013-08-10
    • 1970-01-01
    • 2016-01-10
    • 2014-01-09
    • 1970-01-01
    • 2015-01-17
    • 2016-04-15
    相关资源
    最近更新 更多