0

I am trying to use this program to process a number from outside of a function but when I run the function it will go into a infinite loop and not stop printing.

It works when I take out the inputNumber() after the print command but I need that there?

This is my full code:

def inputNumber():
    try:
        print (userInput)
        Number2 = ('%02d' % (int(userInput)))
        print(Number2)
    except ValueError:
        print("Not an integer! Try again.")
        inputNumber()

    else:
        if int(Number2)<=10:
        #print("Correct")
        if len(str(Number2))==2:
            print("Number Is Good Continue")
        else:
            print("Try Again")
            inputNumber()
        else:
        print("Score Must Be Within 01-10")

userInput = input("Input Score")
inputNumber()

The bit that's not working is when I put anything other than a integer then it should say "Not an integer! Try again." but it will loop this. How can I fix this as I don't see any reason it would be looping.

I've tried using break but it won't work as it is inside a while loop I think?

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
Adam Martin
  • 11
  • 1
  • 6
  • the `inputNumber` method itself should be responsible for calling `input` – Hamms Oct 03 '17 at 20:17
  • hi hamms can you explain? – Adam Martin Oct 03 '17 at 20:19
  • 1
    When the user gives bad input your code should let them try again. But it doesn't. Take 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) to get some ideas about reorganizing your code. – PM 2Ring Oct 03 '17 at 20:21
  • He means that everytime you call `inputNumber()` function it should also call the `userInput`. Define the `userInput` inside the inputNumber() – aspo Oct 03 '17 at 20:21
  • Really, putting calls to `inputNumber()` inside the `inputNumber` function itself isn't a good idea. Kevin explains why in the linked answer, in the section headed "Recursion Will Blow Your Stack". – PM 2Ring Oct 03 '17 at 20:23
  • You can use `if isinstance(userInput, int):` to immediately check if the input is integer or not – aspo Oct 03 '17 at 20:27
  • @deaspo No, that will always return `False`, since `input()` in Python 3 **always** returns a string. – PM 2Ring Oct 03 '17 at 20:28
  • Ooh, thanks for the correction @PM2Ring – aspo Oct 03 '17 at 20:29
  • 1
    thanks, guys i think I'm gonna have to run it inside as it works that way just kinda needed it to be out but cheers guys! – Adam Martin Oct 03 '17 at 20:39

3 Answers3

3

Don't use recursion to replace a loop; Python doesn't do tail-call optimization. Just loop until the input can be converted to a number between 1 and 10, at which point you can explicitly break out of the loop.

def input_number():
    while True:
        n = input("Input score: ")
        try:
            n = int(n)
        except ValueError:
            print("Not an integer! Try again.")
            continue

        if 1 <= n <= 10:
            print("Correct")
            break

        print("Score must be between 1 and 10")

    return '%02d' % (n,)

value = input_number()
chepner
  • 497,756
  • 71
  • 530
  • 681
0

Edited your code: See the following

def inputNumber():
    userInput = input("Input Score: ")
    try:
        print (userInput)
        Number2 = ('%02d' % (int(userInput)))
        print(Number2)
    except ValueError:
        print("Not an integer! Try again.")
        inputNumber()

    else:
        if int(Number2)<=10:
            #print("Correct")
            if len(str(Number2))==2:
                print("Number Is Good Continue")
            else:
                print("Try Again")
                inputNumber()
        else:
            print("Score Must Be Within 01-10")

inputNumber()
aspo
  • 374
  • 2
  • 9
  • 1
    I've had it like this before just needed the input of the number to be outside but I don't think it going to work cheers – Adam Martin Oct 03 '17 at 20:45
0

One way to approach this problem, in order to understand why the loop occurs, when you intended it not to, is to draw a flow chart of the process.

Somewhat simplified, you have inputNumber()-->inputNumber()

In your inputNumber() function, the function itself can potentially be called one of two times:

line 8

line 17

What happens then is that the function in itself will restart. In addition once the inner function resolves, the interpreter returns to where the function call ends and continues to the end of the program.

See my comments below:

def inputNumber(): # Define what happens when you call inputNumber()
    try:
        print (userInput)
        Number2 = ('%02d' % (int(userInput)))
        print(Number2)
    except ValueError:
        print("Not an integer! Try again.")
        inputNumber() # Call inputNumber()

    else:
        if int(Number2)<=10:
        #print("Correct")
        if len(str(Number2))==2:
            print("Number Is Good Continue")
        else:
            print("Try Again")
            inputNumber() # Call inputNumber()
        else:
        print("Score Must Be Within 01-10")

userInput = input("Input Score")
inputNumber() # Call inputNumber

This is known as recursion and can be a useful application in specific contexts under certain memory constraints, but it is generally a concept that should be introduced at a more advanced level - unless a very specific problem requires recursion.

noumenal
  • 1,077
  • 2
  • 16
  • 36