Categories
function python recursion return

Why does my recursive function return None?

91

I have this function that calls itself:

def get_input():
    my_var = input('Enter "a" or "b": ')

    if my_var != "a" and my_var != "b":
        print('You didn\'t type "a" or "b". Try again.')
        get_input()
    else:
        return my_var

print('got input:', get_input())

Now, if I input just “a” or “b”, everything works fine:

Type "a" or "b": a
got input: a

But, if I type something else and then “a” or “b”, I get this:

Type "a" or "b": purple
You didn't type "a" or "b". Try again.
Type "a" or "b": a
got input: None

I don’t know why get_input() is returning None since it should only return my_var. Where is this None coming from and how do I fix my function?

3

  • 16

    You need to do return Dat_Function() when calling it recursively.

    Jul 22, 2013 at 0:31

  • 8

    Just a tip: The idiomatic way of that my_var != "a" and my_var != "b" condition would be my_var not in ('a', 'b')

    – gonz

    May 18, 2016 at 1:04

  • @gonz not necessarily. Now you’re hitting the heap allocating a tuple just to do a simple comparison. Could be painful in a critical path and it’s not much more readable, really.

    – ggorlen

    Apr 29, 2021 at 1:05

128

It is returning None because when you recursively call it:

if my_var != "a" and my_var != "b":
    print('You didn\'t type "a" or "b". Try again.')
    get_input()

..you don’t return the value.

So while the recursion does happen, the return value gets discarded, and then you fall off the end of the function. Falling off the end of the function means that python implicitly returns None, just like this:

>>> def f(x):
...     pass
>>> print(f(20))
None

So, instead of just calling get_input() in your if statement, you need to return it:

if my_var != "a" and my_var != "b":
    print('You didn\'t type "a" or "b". Try again.')
    return get_input()

7

  • Shouldn’t it run through the if statement again if it is called recursively? I don’t understand why it wouldn’t return a value.

    – Cate

    Jul 22, 2013 at 0:35

  • 1

    Nope. See my edit. The recursion happens, and then you discard what the recursion returns.

    – roippi

    Jul 22, 2013 at 0:38

  • 1

    You lost me with that main() bit… You can fail as many times as you want to, the one that “succeeds” will return my_var, which will get passed down (returned) through all of the recursive calls all the way down to the original caller. Which, yes, is main().

    – roippi

    Jul 22, 2013 at 0:54


  • 2

    Use return for recursive function in order to put its value into the stack , so that when function will do recursion values from the stack are taken one by one. If you don’t use return , the stack will collect only “None” values.

    Apr 23, 2016 at 18:59

  • 1

    you, sir, are a genius! That was not intuitive to me.

    – jouell

    Jun 11, 2019 at 14:38

12

To return a value other than None, you need to use a return statement.

In your case, the if block only executes a return when executing one branch. Either move the return outside of the if/else block, or have returns in both options.

1

  • I’ve tried moving it out of the block, but to no avail. Instead of returning the correct value, it returns the first incorrect value. Also, I don’t want a return statement for the if part of the if/else statement because I want the function to only return a correct value.

    – Cate

    Jul 22, 2013 at 0:39

2

def get_input():
    my_var = input('Enter "a" or "b": ')

    if my_var != "a" and my_var != "b":
        print('You didn\'t type "a" or "b". Try again.')
        return get_input()
    else:
        return my_var

print('got input:', get_input())