Home > Enterprise >  Limiting user input without exceptions
Limiting user input without exceptions

Time:03-31

I tried the standard "guess random number game" as my very first tiny project in python and decided to pimp it a little. My goal was to make the program resilient against ValueError crashes by user input while making it as flexible as (my meager skills make) possible. I ran into the problem of the input() function only returning strings and my solution with multiple levels of exceptions just seems so unbearably clunky and verbose.

I have this function that asks the user how many guesses they want and returns the answer.

def guess_max_asker():
    while True:

        guess_max_temp = input("How many guesses do you want? (1 - 10)\n> ")

        try:  # lvl 1 checks if input is a valid int
            guess_max_temp2 = int(guess_max_temp) #ugly 
            if 11 > guess_max_temp2 > 0:
                print(f"Ok! You get {guess_max_temp2} tries!")
                return guess_max_temp2
            else:
                print("That's not a valid number..")
                continue

        except ValueError:
            print("ValueError!") # It's alive!
            try:  # lvl 2 checks if input is float that can be rounded
                guess_max_temp2 = float(guess_max_temp)
                print(f"I asked for an integer, so I'll just round that for you..")
                return round(guess_max_temp2)

            except ValueError:  # lvl 3 checks if input is a valid string that can be salvaged
                emergency_numbers_dict = {"one": 1, "two": 2, "three": 3, "four": 4, "five": 5,
                                          "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10}
                if guess_max_temp.lower() in emergency_numbers_dict:
                    print(f'I asked for an integer, but I will let "{guess_max_temp}" count..')
                    return emergency_numbers_dict[guess_max_temp]
                else:
                    print("That's not a valid answer..")
                    continue

guess_max = guess_max_asker()

Is there a more elegant way than a "while True" loop? I tried and failed to find a way to make Python rerun a simple if statement akin to "continue" with "while" loops. If I could make Python recognise the input as a different type, I could play around with isinstance(), but I don't see how. I'm sure the answer is painfully obvious, but believe me that I've tried.

CodePudding user response:

The "loop around a try/except" approach is pretty standard, so you're on the right track.

You can clean it up a bit with a helper function like:

def input_int(prompt):
    while True:
        response = input(prompt)
        try:
            return int(response)
        except ValueError:
            print("ValueError -- try again")

Which you could then use like:

user_int = input_int("Input an integer: ")
print("Accepted: ", user_int)

Example:

Input an integer: c
ValueError -- try again

Input an integer: 1.2
ValueError -- try again

Input an integer: 1
Accepted:  1

CodePudding user response:

Sticking to your original code as far as possible, you could try:

def guess_max_asker():
    while True:
        guess_max_temp = input("How many guesses do you want? (1 - 10)\n> ")
        if guess_max_temp.isnumeric():
            if int(guess_max_temp)>11:
                print("That's not a valid number")
            else:
                return int(guess_max_temp)
        else:
            emergency_numbers_dict = {"one": 1, "two": 2, "three": 3, "four": 4, "five": 5,
                                      "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10}
            if guess_max_temp not in emergency_numbers_dict:
                print("That's not a valid answer..")
            else:
                print(f'I asked for an integer, but I will let "{guess_max_temp}" count..')
                return emergency_numbers_dict[guess_max_temp]     
        
guess_max = guess_max_asker()
  • Related