Search code examples
pythonfunctionnonetype

Why does this Python function return a None error?


In the textbook A Beginner's Guide to Python 3, there is an example of a function in Chapter 11. The program is:

def get_integer_input(message):
    """
    This function will display the message to the user
    and request that they input an integer.

    If the user enters something that is not a number
    then the input will be rejected
    and an error message will be displayed.

    The user will then be asked to try again."""

    value_as_string = input(message)
    while not value_as_string.isnumeric():
        print("The input must be an integer greater than zero.")
        value_as_string = input(message)
        return int(value_as_string)


age = get_integer_input("Please input your age: ")
age = int(age)
print("age is", age)`

The output, according to the textbook, should be:

Please input your age: 21
age is 21

But I get:

Please input your age: 20

Traceback (most recent call last):
  File "/Users/RedHorseMain/Documents/myPythonScripts/A Beginners Guide to Python 3/6.10.3 getAge.py", line 20, in <module>
    age = int(age)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'

However, if I first enter a string instead of an integer, the error that the function is supposed to protect against, it works:

Please input your age: Red

The input must be an integer greater than zero.

Please input your age: 21

age is 21

Would someone please explain why the function is returning a 'NoneType'?


Solution

  • A simple fix:

    def get_integer_input(message):
        """
        This function will display the message to the user
        and request that they input an integer.
    
        If the user enters something that is not a number
        then the input will be rejected
        and an error message will be displayed.
    
        The user will then be asked to try again."""
    
        value_as_string = input(message)
        print(value_as_string)
        while not value_as_string.isnumeric():
            print("The input must be an integer greater than zero.")
            value_as_string = input(message)
            return int(value_as_string)
        return int(value_as_string)
    
    
    age = get_integer_input("Please input your age: ")
    age = int(age)
    print("age is", age)
    

    Added the return value just beneath the while loop in get_integer_input as otherwise it never actually returns anything because the value_as_string counts as numeric when checked by that while loop and thus is not false and so the while loop never begins and since it sees no other statements by default the age = get_integer_input("Please input your age: ") gets a NoneType back and when it attempts to resolve that to an int: age = int(age) it throws an error as you can't convert None into a usable number.

    As such putting a return value outside of that while loop solves the issue as now the function is returning a value instead of defaulting to none on a no return.