2

Python==3.6.9

def test():
    a = 2
    try:
        1 / 0
    except Exception as exc:
        return a
    finally:
        a += 1
        print(a)

print(test())

output is:

3
2

It's obvious that finally executes before return, if a is a immutable type, id(a) is different between finally scope and try\except scope;

I want to know how did this happen? Thanks

Wynter
  • 93
  • 4
  • 1
    `try` block has no scope in python. For the new `id(a)` explanation look here https://stackoverflow.com/questions/1047021/overriding-in-python-iadd-method. – 4xy Jan 08 '21 at 08:37
  • 1
    The mechanism behind the try statement has to ensure the finally block runs, so if you return from the try or catch blocks the value to return (in this case `2`, as that's what `a` is when the return statement is reached) is stored to be returned once the finally block has run (unless you return from the finally block, in which case that stored value is discarded). – jonrsharpe Jan 08 '21 at 08:45
  • @jonrsharpe thanks, your answer is very useful, can i understand that finally stores information like a function, but does not use it if return before? – Wynter Jan 12 '21 at 03:10

2 Answers2

0

The built-in try statement does not create its own scope. Modules, classes, and functions create scope.

A complete description of Python scopes and namespaces in the docs.

Although scopes are determined statically, they are used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:

  • the innermost scope, which is searched first, contains the local names
Kuldeep Singh Sidhu
  • 3,748
  • 2
  • 12
  • 22
  • Seems like this answer does not address the elements of the question directly. There isn't any variable called `b`. There is no `add` function. – Harsh Verma Jan 08 '21 at 09:13
0

One of the great things about the finally block is that it guarantees an operation is executed when we exit the scope of the try-catch block. We are forced to exit the scope when we return from the function. So, before we return we do the guaranteed task in the finally block first. If we didn't do this task, there can be bad consequences. For Eg :

Assume I create a connection in try block and I close it in finally block. If I return the connection in the catch block without closing it in the finally block, the function caller can start operating on a supposedly dead connection.

Hence, as you already know, if we didn't have return :

def test():
    try:
        1 / 0
    except Exception as exc:
        print("hi")
    finally:
        print("bye)

print(test())

The output will be

hi
bye
Harsh Verma
  • 529
  • 6
  • 10