Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return in Recursive Function

I have just started learning python (v3.2.3) and have encountered an odd problem about the return in this function:

def test(x):     if x > 9 :         test(x - 10)     else:         print('real value',x)         return x  x = int(input()) y = test(x) print('this should be real value',y) 

When I run it, I get:

45 real value 5 this should be real value None 

But I expected:

45 real value 5 this should be real value 5 

I tried adding return x outside of if and I got the default input value. Can anyone please explain how return works?

like image 573
Alex Key Avatar asked Jul 06 '12 05:07

Alex Key


People also ask

Do recursive functions have to return something?

All functions - recursive or not - have one or more return . The return may or may not include a value. It is for you to decide when you write the function. All explicit written return statements must return the correct type.

How do you return a recursion statement?

Now, one important thing before coding a recursion is that you must understand how mathematically it is supposed to work. In the case of sum of n numbers we know that if sum of n-1 numbers is known we could return that sum + n . Now what if do not know that sum . Well, we find sum of n-2 terms and add n-1 to it.

What is return address in recursion?

Usually when there is a recursive call to a function then in the stack the return address points to the next instruction after the function call.

Does return stop a recursive function?

Aside from that, if you've called your recursive function a given number of times, returning from the function would return you to the previous call of that function. A return statement won't stop all the prior recursive calls made from executing.


1 Answers

You invoke test(45). This tests whether 45 > 9, which is true, so it invokes test(35) (45 - 10), without returning its result. The same thing happens with test(25) and test(15), until finally test(5) is invoked.

This prints 'real value 5', and then returns 5. But returning a result from a function always returns it to the direct caller of this function. It doesn't jump immediately out through several calls; after all, the caller might want to do something with the returned result before returning something to it's caller. In this case though, only test(5) returns anything at all; all the others call test(x - 10), wait for that to return, ignore whatever it does return, and then (implicitly) return None. Since the outermost invocation test(45) is one of these cases, what you get is None.

Here's an attempt at a visualisation of what happens:

test(45): | test(35): | | test(25): | | | test(15): | | | | test(5): | | | | | print('real value',5) | | | | | return 5 to test(15) | | | | return None to test(25) | | | return None to test(35) | | return None to test(45) | return None 

You didn't call test(5) in the interpreter, test(5) was called from inside another function call. So the return from test(5) goes to that function call. The fact that this is a function calling itself is completely irrelevant. You'd get exactly the same results if your code looked like this:

def test45(x):     if x > 9 :         test35(x - 10)     else:         print('real value',x)         return x  def test35(x):     if x > 9 :         test25(x - 10)     else:         print('real value',x)         return x  def test25(x):     if x > 9 :         test15(x - 10)     else:         print('real value',x)         return x  def test15(x):     if x > 9 :         test5(x - 10)     else:         print('real value',x)         return x  def test5(x):     if x > 9 :         print 'No more tests :('     else:         print('real value',x)         return x 

The test(x) function you call with 'x=45' is same as calling test45(45). I hope you can see why it's obvious that None should be returned when recursion isn't involved. Well, when recursion is involved, nothing changes. The return statement neither knows nor cares whether it's returning from a recursively invoked function, it behaves exactly the same way in either case.

In fact, recursion isn't anything "special" at all; it behaves exactly the same way as ordinary function calls. You receive information from the thing that called you via arguments, and you return information to the thing that called you by returning. If you don't return something (perhaps only in one arm of an if), then None will be returned to your caller, regardless of whether you call any other function in that branch, regardless of what that function might return if you do call something, and regardless of whether the function you call happens to be the same function you're inside.

like image 161
Ben Avatar answered Sep 21 '22 03:09

Ben