在finally子句中返回值是否错误?

Lau*_*RTE 7 python try-finally python-3.x

如果尝试以下代码,则会看到未返回正常的块返回值,但最终的块返回值为:

>>> def f():
...     try:
...         return "normal"
...     finally:
...         return "finally"
... 
>>> f()
'finally'
Run Code Online (Sandbox Code Playgroud)

一个更高级的示例是在每个return语句中调用一个函数:

在这种情况下,我可以看到:

  • 在普通块中,对show函数进行求值(但不返回),
  • 在finally块中,对show函数进行求值并返回:
>>> def show(x):
...     print(x)
...     return x
... 
>>> def g():
...     try:
...         return show("normal")
...     finally:
...         return show("finally")
... 
>>> g()
normal
finally
'finally'
Run Code Online (Sandbox Code Playgroud)

在finally子句中有return语句是一种好习惯吗?还是它是一个潜在的错误(应通过代码分析工具或代码审查来检测)?

编辑

另一个有例外的示例:

>>> def f():
...     try:
...         raise ValueError("bad")
...     finally:
...         return "good"
... 
>>> f()
'good'
Run Code Online (Sandbox Code Playgroud)

奇怪的!

sch*_*ggl 3

恕我直言,如果相关或块中存在语句,则在子句中使用returnin是不好的做法。finallyreturntryexcept

try:
    # lots of spaghetti code
    return fancy_expression_with_side_effects
except AllKindsOfError:
    # lots of alternative spaghetti code
finally:
    # many a mouse wheel spin down the module
    # lots of clean up
    return eternal_return_value
Run Code Online (Sandbox Code Playgroud)

虽然这将构成有效的 Python,但实际上不应该。第一个return语句将部分执行:您将观察评估的副作用fancy_expression_with_side_effects(尝试return print('foo')那里),并且它仍然不会返回该表达式的值。我曾经在这种情况下摸不着头脑几个小时。

但是,如果其中的 return 语句finally是唯一的 return 语句,那么人们将能够以一种简单的预期方式轻松地遵循逐步执行流程,并且我没有看到太多错误,但仍然会要非常小心:在许多软件项目中,你可能是知道这些东西的高级 Python 人员,但是你如何保证其他人return以后不会在其他地方添加语句呢?