Finally 块在 try 块中的 return 语句之前运行,如下例所示 - 返回
False
而不是 True
:
>>> def bool_return():
... try:
... return True
... finally:
... return False
...
>>> bool_return()
False
同样,以下代码返回Finally块中设置的值:
>>> def num_return():
... try:
... x=100
... return x
... finally:
... x=90
... return x
...
>>> num_return()
90
但是,对于finally块中没有return语句的变量赋值,为什么finally块更新的变量值没有被try块返回呢? finally 块中的变量在finally 块中的作用域是本地的吗?或者 try 块的返回值保存在内存缓冲区中并且不受 finally 块中的赋值影响? 在下面的示例中,为什么输出是 100 而不是 90?
>>> def num_return():
... try:
... x=100
... return x
... finally:
... x=90
...
>>> num_return()
100
类似下面的例子:
In [1]: def num_return():
...: try:
...: x=[100]
...: return x
...: finally:
...: x[0] = 90
...:
In [2]: num_return()
Out[2]: [90]
In [3]: def num_return():
...: try:
...: x=[100]
...: return x[0]
...: finally:
...: x[0] = 90
...:
In [4]: num_return()
Out[4]: 100
帮助确认其他人的回答的一个小实验是将
x
替换为单值列表,如下所示:
def num_return():
try:
x=[100]
return x
finally:
x[0] = 90
现在返回的值是
[90]
,所以列表确实在finally块中被修改了。
但是如果你返回
x[0]
,你会得到100
(即使我们只是基于列表本身确实在finally块中发生变化的事实)。
In [1]: def num_return():
...: try:
...: x=[100]
...: return x
...: finally:
...: x[0] = 90
...:
In [2]: num_return()
Out[2]: [90]
In [3]: def num_return():
...: try:
...: x=[100]
...: return x[0]
...: finally:
...: x[0] = 90
...:
In [4]: num_return()
Out[4]: 100
当你说
return x
时,Python会将变量x
在该点的值保存为返回值。稍后更新 x 不会影响这一点。
以下条款摘自:https://docs.python.org/3/tutorial/errors.html(第 8.6 节)
如果 try 语句到达break、continue 或 return 语句,finally 子句将在
、break
或continue
语句执行之前执行。return
在第一个示例中,return False 在 return True 之后执行,因此是结果。这也解释了第二个例子。
对于最后一个,您的 return x 保存了代码中该点的 x 值,更改变量 x 的值不会更改 return 语句的值。
我认为你遇到的问题与价值分配比
try
和finally
所做的更相关。我建议阅读关于 Python 名称和值的事实和神话。
当您返回一个值时,就像将值分配给变量一样,例如
result
,并且finally
始终执行以重新分配值。然后,您的示例代码可能表示为:
# try
result = True # return
# finally
result = False # return (reassign value)
print(result) # Output: False
# try
x = 100
result = x # return
# finally
x = 90
result = x # return (reassign value)
print(result) # Output: 90
# try
x = 100
result = x # return
# finally
x = 90 # no return so result not updated
print(result) # Output: 100
print(x) # Output: 90 (x is changed actually)
# try
x = [100]
result = x # return the list (result refer to a list and list is mutable)
# finally
x[0] = 90 # changing the list in-place so it affects the result
print(result) # Output: [90]
# try
x = [100]
result = x[0] # return the integer (result refer to the integer)
# finally
# changing the list in-place which have no effect to result unless reassign value by return x[0]
x[0] = 90
print(result) # Output: 100
print(x) # Output: [90] (x is changed actually)
所以 try 是“尝试这个代码” 最后是“如果一切顺利,那么最后就这样做”