Finally 总是在 try 块返回之前运行,那么为什么 finally 块中的更新不会影响 try 块返回的变量值?

问题描述 投票:0回答:6

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
python python-3.x
6个回答
12
投票

帮助确认其他人的回答的一个小实验是将

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

7
投票

当你说

return x
时,Python会将变量x
在该点
保存为返回值。稍后更新 x 不会影响这一点。


5
投票

以下条款摘自: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 语句的值。


1
投票

我认为你遇到的问题与价值分配比

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)


-2
投票

所以 try 是“尝试这个代码” 最后是“如果一切顺利,那么最后就这样做”

© www.soinside.com 2019 - 2024. All rights reserved.