Search code examples
pythonvariablesrecursionscopelocal

Recursive function variable scope confusion in Python


def my_function():
    try:
        number = int(input("What is your favorite number?\n\n"))
    except ValueError: #if anything but an integer was given as the str to input
        my_function() #recursive to ask again
    return number
my_function()

This throws the exception UnboundLocalError: local variable 'number' referenced before assignment if I go through the recursive scope at least once and then give a valid input. I thought the variable number should point to a different object every iteration of the function. What am I missing here?

I recognize I can simply move return number into the try block to achieve this functionality, but why do I have to?


Solution

  • I thought the variable number should point to a different object every iteration of the function.

    What causes the local variable number to get set in the current call? Answer: number = int(input("What is your favorite number?\n\n")). Does it always get assigned? Answer: No, not if int raises an exception. When does the recursive call happen? Answer: when, and only when, the exception is raised. Therefore, when a recursive call happens, does number have a value set in the current call? Answer: No.

    I recognize I can simply move return number into the try block to achieve this functionality

    No; this does not work! If the exception is raised, then return number does not happen in the current call. The recursive call will occur, and then the value returned from that recursive call will be ignored. In the current call, control flow reaches the end of the function, and None is returned. You would have to explicitly return the value from the recursive call, or explicitly assign it to number and then return that afterward.

    But that's ugly. You should just use a loop for this, like everyone else does.