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.
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.