Search code examples
pythonfunctionrecursionreturn-value

Looking for explanation of what's happening in this recursive Python snippet?


The snippet:

def fun(a):
        if a > 30:
            return 3
        else:
            return a + fun(a+3)
print(fun(25)) # prints 56

Now my question is this: The return from the function does not seem assigned specifically to a. So how does the program ever reach the a > 30 branch, and terminate?

In practice, the snippet prints 56. How does the function arrive at this value? One answer seems to be: the return value of fun(a+3) is indeed assigned to a, resulting in a becoming 53 i.e. (25 + (25 + 3)) on the first pass and 56 i.e. (53 + 3) on the next pass.

I tried:

def fun(a):
        if a > 30:
            return 3
        else:
            return fun(a+3)
print(fun(25)) 

And got 3. So a + fun(a + 3) should return 28 to the print command.


Solution

  • One way to explain and visualize what's happening is with print debugging.

    With the additional print() calls added (and lvl to track each level of recursion):

    def fun(a, lvl=0):
        print("  " * lvl, f"fun({a}, {lvl})", end="")
        if a > 30:
            print(" => 3")
            return 3
        else:
            print(f" => {a} + fun({a + 3}, {lvl + 1})")
            return a + fun(a + 3, lvl + 1)
    
    print(fun(25)) # prints 56
    

    You'll see the following output breaking it all down:

    ❯ python foo.py
     fun(25, 0) => 25 + fun(28, 1)
       fun(28, 1) => 28 + fun(31, 2)
         fun(31, 2) => 3
    56 
    

    Because 25 + 28 + 3 = 56

    Each line represents one call of the same function, each with its own independent scope. The variable a never gets assigned to nor shared between these calls/scopes.