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()