2

def gender():

Creating a function that should return True or False

    gener = input('Choose \"1\" for Male or \"2\" for Female: ') 

"gener" should receive "1" or "2" as string

    if gener == '1':
        print('You selected Male')
        return True
    elif gener == '2':
        print('You selected Female')
        return False
    else:

Here happens the problem. It should execute again the function gender() so the user could reinsert "1" or "2" correctly

        print('Invalid character')
        gender()

But when printing the function gender() it returns "None" even if gender() is executed again in order to receive a new value, continuing with the value of Else statement

print(gender())
Artier
  • 1,648
  • 2
  • 8
  • 22
  • 2
    It's usually a bad idea to recursively call functions unless you really have some recursive algorithm. For your problem, have a look at [Asking the user for input until they give a valid response](https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) for ideas. – Thierry Lathuille Feb 04 '18 at 09:21
  • @ThierryLathuille Thats an awfully nice post. – Patrick Artner Feb 04 '18 at 09:28
  • Possible duplicate of [Asking the user for input until they give a valid response](https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) – Patrick Artner Feb 04 '18 at 09:29
  • `from itertools import repeat, dropwhile; gender = next(dropwhile(lambda x: x not in ('1', '2'), (input() for _ in repeat(None))))` – Eli Korvigo Feb 04 '18 at 09:41
  • 1
    All the code needed to reproduce the error is present in the question. The question is not fully about "How to ask for Input until valid?" but rather about why this codes `returns None` - see answer for why. – Patrick Artner Feb 04 '18 at 09:45
  • Here is a non-recursive one-liner for you `from itertools import repeat; gender = next(filter(lambda x: x in ('1', '2'), (input() for _ in repeat(None))))` – Eli Korvigo Feb 04 '18 at 10:08

1 Answers1

-1

In python every function returns None if you do not return anything. Check your if .. .elif ... else - where does the else return anything?

It does not - it just calls gender() (and then implicitly returns None)

Change it to return the return of that function call:

 if gener == '1':
    print('You selected Male')
    return True
elif gener == '2':
    print('You selected Female')
    return False
else:
    print('Invalid character')
    return gender()

This would fix your code, to make it better do not use recursion.


Using unneded recursion will pack new data onto call stacks all the time. You can optimize it by using a loop instead of recursing:

def gender():
    """Choose Male or Femal, return True for Male and False for Female"""

    gener = ""   # prepare an invalid input
    while gener not in ['1','2']:  # loop until input gets valid
        gener = input('Choose "1" for Male or "2" for Female: ')

    if gener == '1':
        print('You selected Male')
        return True
    # elif gener == '2':
    #    print('You selected Female')
    #    return False
    else: # no need for explicit check, it can only be 1 or 2 
        print('You selected Female')
        return False

print(gender())

Sidenote for political correctness:

  • not all humans on earth term themself as male or female
  • not all humans on earth wan't to make this decision known
  • gender might change over a livetime
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69