return finally 子句中的值是否错误
Is it an error to return a value in a finally clause
如果我尝试下面的代码,我发现普通块 return 的值不是 returned,但最终块 return 的值是:
>>> def f():
... try:
... return "normal"
... finally:
... return "finally"
...
>>> f()
'finally'
一个更高级的例子是在每个return语句中调用一个函数:
在那种情况下,我可以看到:
- 在普通块中,
show
函数被求值(但不是 return),
- 在 finally 块中,计算
show
函数并 returned:
>>> def show(x):
... print(x)
... return x
...
>>> def g():
... try:
... return show("normal")
... finally:
... return show("finally")
...
>>> g()
normal
finally
'finally'
在 finally 子句中使用 return 语句是一种好习惯吗?
或者,这是一个潜在的错误(应该通过代码分析工具或代码审查来检测)?
编辑
另一个例外的例子:
>>> def f():
... try:
... raise ValueError("bad")
... finally:
... return "good"
...
>>> f()
'good'
奇怪!
如果您 运行 脚本同时包含印刷品,会更容易理解。它表明它实际上进入 try 块内部执行所有操作(实际上几乎 returns),只有 finally 部分覆盖第一个 return 语句。
>>> def f():
... try:
... print("try")
... return "try"
... finally:
... print("finally")
... return "finally"
...
>>> f()
try
finally
'finally'
这是一个好习惯吗?我认为有时这是必要的,我认为这没有任何问题。执行时的 finally 块也会释放资源和其他东西,所以我看不出这是错误的原因。 (我不会说这是一个好的做法,但它没有错。)
在我看来,在 finally 子句中使用 return 语句不是最佳做法,因为要 returned 的值始终是 finally 子句中的值。
如果您想 始终 return 相同的值而不管函数的功能如何,这可能是最佳实践。
进行评估是因为您 运行 python shell 中的此代码。
在 return 情况下,我认为最佳做法是仅使用 try 和 except。
def myfunc(x):
try:
return x / 0
except:
return x
a = myfunc(20)
print(a)
恕我直言,如果在相关的 try
或 except
块中有 return
语句,那么在 finally
子句中使用 return
是不好的做法.
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
虽然这会构成有效 Python,但实际上不应该。第一个 return
语句将 部分 执行:您将观察评估 fancy_expression_with_side_effects
的副作用(在那里尝试 return print('foo')
)并且它仍然 not return 该表达式的值。在那种情况下,我曾经摸不着头脑几个小时。
但是,如果 finally
中的 return 语句是唯一的 return 语句,则可以很容易地遵循分步执行流程简单的预期方式,我没有看到太多错误,但仍然会非常小心:
在许多软件项目中,您可能是了解这些东西的资深 Python 人,但是您有什么保证以后不会有人在其他地方添加 return
语句?
如果我尝试下面的代码,我发现普通块 return 的值不是 returned,但最终块 return 的值是:
>>> def f():
... try:
... return "normal"
... finally:
... return "finally"
...
>>> f()
'finally'
一个更高级的例子是在每个return语句中调用一个函数:
在那种情况下,我可以看到:
- 在普通块中,
show
函数被求值(但不是 return), - 在 finally 块中,计算
show
函数并 returned:
>>> def show(x):
... print(x)
... return x
...
>>> def g():
... try:
... return show("normal")
... finally:
... return show("finally")
...
>>> g()
normal
finally
'finally'
在 finally 子句中使用 return 语句是一种好习惯吗? 或者,这是一个潜在的错误(应该通过代码分析工具或代码审查来检测)?
编辑
另一个例外的例子:
>>> def f():
... try:
... raise ValueError("bad")
... finally:
... return "good"
...
>>> f()
'good'
奇怪!
如果您 运行 脚本同时包含印刷品,会更容易理解。它表明它实际上进入 try 块内部执行所有操作(实际上几乎 returns),只有 finally 部分覆盖第一个 return 语句。
>>> def f():
... try:
... print("try")
... return "try"
... finally:
... print("finally")
... return "finally"
...
>>> f()
try
finally
'finally'
这是一个好习惯吗?我认为有时这是必要的,我认为这没有任何问题。执行时的 finally 块也会释放资源和其他东西,所以我看不出这是错误的原因。 (我不会说这是一个好的做法,但它没有错。)
在我看来,在 finally 子句中使用 return 语句不是最佳做法,因为要 returned 的值始终是 finally 子句中的值。
如果您想 始终 return 相同的值而不管函数的功能如何,这可能是最佳实践。
进行评估是因为您 运行 python shell 中的此代码。
在 return 情况下,我认为最佳做法是仅使用 try 和 except。
def myfunc(x):
try:
return x / 0
except:
return x
a = myfunc(20)
print(a)
恕我直言,如果在相关的 try
或 except
块中有 return
语句,那么在 finally
子句中使用 return
是不好的做法.
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
虽然这会构成有效 Python,但实际上不应该。第一个 return
语句将 部分 执行:您将观察评估 fancy_expression_with_side_effects
的副作用(在那里尝试 return print('foo')
)并且它仍然 not return 该表达式的值。在那种情况下,我曾经摸不着头脑几个小时。
但是,如果 finally
中的 return 语句是唯一的 return 语句,则可以很容易地遵循分步执行流程简单的预期方式,我没有看到太多错误,但仍然会非常小心:
在许多软件项目中,您可能是了解这些东西的资深 Python 人,但是您有什么保证以后不会有人在其他地方添加 return
语句?