简体   繁体   中英

Finally always runs just before the return in try block, then why update in finally block not affect value of variable returned by try block?

Finally block runs just before the return statement in the try block, as shown in the below example - returns False instead of True :

>>> def bool_return():
...  try:
...    return True
...  finally:
...    return False
...
>>> bool_return()
False

Similarly, the following code returns value set in the Finally block:

>>> def num_return():
...  try:
...    x=100
...    return x
...  finally:
...    x=90
...    return x
...
>>> num_return()
90

However, for variable assignment without return statement in the finally block, why does value of variable updated by the finally block not get returned by the try block? Is the variable from finally block scoped locally in the finally block? Or is the return value from the try block held in memory buffer and unaffected by assignment in finally block? In the below example, why is the output 100 instead of 90?

>>> def num_return():
...  try:
...    x=100
...    return x
...  finally:
...    x=90
...
>>> num_return()
100

Similarly the following example:

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

A little experiment to help confirm what others have answered, is to replace x with a single-value list, like this:

def num_return():
  try:
    x=[100]
    return x
  finally:
    x[0] = 90

now the value returned is [90] , so the list is indeed modified in the finally block.

BUT if you return x[0] , you get 100 (even though we just based the fact that the list itself does change in the finally block).


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

When you say return x , Python saves the value of the variable x at that point as the return value. Updating x later doesn't affect this.

The following clause was taken from: https://docs.python.org/3/tutorial/errors.html (section 8.6)

If the try statement reaches a break, continue or return statement, the finally clause will execute just prior to the break , continue or return statement's execution.

On your first example, return False is executed after return True, hence the result. This also explains the second example.

For the last one, your return x saves the value of x at that point of your code, changing the value of the variable x does not change the value of the return statement.

I think the problem you have is more related to value assignment than what try and finally do. I suggest to read Facts and myths about Python names and values .

When you return a value, it just like assigning the value to a variable, result for example, and finally always execute to reassign the value. Then, your example code may be represent as:

# 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)

So try is "Try this code" finally is "If everything goes properly then finally do this"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM