Reputation: 9714
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
Upvotes: 23
Views: 3169
Reputation: 1173
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)
Upvotes: 1
Reputation: 338
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
orreturn
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.
Upvotes: 5
Reputation: 13413
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
Upvotes: 12
Reputation: 694
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.
Upvotes: 7