Recursive loops in Python

Question:

I’m working on the following recursive loop example from the Python Essentials 1, and I don’t really understand what’s happening, hoping someone can shed some light.

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

 print(fun(25))

The output is 56. I don’t really understand what’s happening with the function – it’s almost like it’s taking a + 3 making 28, and that value is then substituted into a then returned, however I’m not sure if that’s what’s actually happening and I don’t want to ‘decide’ that’s the case if it’s not.

Where it gets really interesting is when I started value substitution to try and make sense of it, substituting values in place of the 3. I get the following:

return a + fun (a + 0) = // RecursionError: maximum recursion depth exceeded in comparison
return a + fun(a + 1) = 168
return a + fun(a + 2) = 84
return a + fun(a + 3) = 56
return a + fun(a + 4) = 57
return a + fun(a + 5) = 58
return a + fun(a + 6) = 28
return a + fun(a + 7) = 28

In fact any integer value greater than or equal to 6 seems to give the same answer, so I would assume I was wrong with my initial analysis of what’s happening.

I also tried to put a while loop in there to see what was happening as below:

def fun(a):
    i = 1
    if a > 30:
        return 3
    else:
        while i <= 10:
            return a + fun(a + i)
            i += 1
            print(i)
        

print(fun(25))

However this finishes the program with a value displayed of 168, presumably as the value of a is now over 30.

I think I may be making several massively erroneous assumptions here, hoping someone can help 🙂

Asked By: user1047228

||

Answers:

You just have to follow step by step.

The first time you call fun with a=25. This isn’t above 30, so you hit the line

return a + fun(a + 3)

which is

return 25 + fun(25 + 3)

so the result is 25 + fun(28). As 28 isn’t above 30 it’s going to do the same again, effectively turning that first return into

return 25 + (28 + fun(28 + 3))

or

return 25 + (28 + fun(31))

Now, 31 is greater than 30 so this call will return 3 directly, giving a final result of 25 + 28 + 3 which is 56.

Answered By: Kemp

Little breakdown of your code :

if a > 30 : the function terminates and return 3 (i.e. a is in ]30, infinity[.
else : this will compute fun(x) with x = a+3 until x reaches 30.

for 25 we will have then :

25 + fun(25+3)
25 + fun(28)
25 + 28 + fun(28+3)
25 + 28 + fun(31)
25 + 28 + 3
53 + 3
56

Python will have a recursion each time it is needed (Hence each call of your fun(a)).

Answered By: Th3Wh1t3Q

The concept of recursion is to go deeper in the called function every time the condition is not met.

Here we check everytime the function is called if the value passed, here a, met the condition IS a HIGHER THAN 30.

If we execute step by step for fun(25) we got this :

First depth :

IS 25 HIGHER THAN 30 ? => False

Then we return `25 + fun(25 + 3)` or `25 + fun(28)` # We call a second time `fun()`

Second depth :

IS 28 HIGHER THAN 30 ? => False

Then we return `28 + fun(28 + 3)` or `28 + fun(31)` # We call a third time `fun()`

Third depth :

IS 31 HIGHER THAN 30 ? => True

Then we return 3 this time # we don't go deeper because the condition is met. From this point we will return to the top and adding every results have previously.

Once we got to the bottom we have to return to each depth until reaching level 1. If we do this we got this :

result = 25 + (28 + (3))

result = 25 + (31)

result = 56

Answered By: Aesahaettr

Each function call has its own argument. It’s always named a, but the value is different. Using something called equational reasoning (which requires pure functions without side effects to work properly, but fun happens to be pure), we can trace this as follows:

fun(25) == 25 + fun(28)
        == 25 + 28 + fun(31)
        == 25 + 28 + 3
        == 53 + 3
        == 56

In what you were doing, any value k >= 6 makes fun(a + k) immediately return 3. Only the smaller values allow one or more additional recursive calls. (0, of course, leads to infinite recursion, because the argument makes no progress towards the base case.)

No recursive call changes the value of a in the caller; they simply get their own (progressively larger) value of a when called.

Answered By: chepner
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.