I need to add a validation whilst in a while loop.
However when I use this validation it doesn't work and instead only comes up with the error message saying I haven't used a base 10/an integer when I want it to come up with the validation error message and let the user try again.
I don't know if having it in a while loop makes the validation I use any different, does it?
Also do I need to change this "def inputNumber(message):" to what my input is stored as?
And this "userInput = int(input(message))" to what my input is stored as?
import time
import random
question = 0
score = 0
name = input("What is your full name?")
print ("Hello " + name, "welcome to The Arithmetic Quiz. Use integers to enter the answer!")
time.sleep(2)
operands1 = list(range(2, 12))
operators = ["+","-","x"]
operands2 = list(range(2, 12))
while question < 10:
operand1 = random.choice(operands1)
operand2 = random.choice(operands2)
operator = random.choice(operators)
def inputNumber(message):
while True:
try:
userInput = int(input(message))
except ValueError:
print("Not an integer! Try again.")
continue
else:
return userInput
break
user_answer =int(input('{} {} {} = '.format(operand1, operator, operand2)))
I doubt you want to have your function definitions within a while loop like you're doing here:
while question < 10:
...
def inputNumber(message):
...
Instead, you can define the function outside the loop and call it x number of times from a loop elsewhere. E.g.
def inputNumber(message):
...
return userInput
while question < 10:
# pick random numbers/operators
...
# call inputNumber() with numbers/operators as message. Return user_answer
user_answer = int(inputNumber('{} {} {} = '.format(operand1, operator, operand2)))
# check if the answer is correct
...
# increment question so it doesn't run infinitely
question += 1
#user6104134 has already solved this problem; however, I'd like to provide an answer for anyone else having similar issues.
Try this solution
import random
import time
question = 0
score = 0
def inputnumber(prompt):
while True:
response = raw_input(prompt)
try:
if isinstance(response, int):
return int(response)
else:
print "Not an integer! Try again."
except ValueError:
print "Not an integer! Try again."
name = raw_input("What is your full name? ")
print ("Hello " + name, "welcome to The Arithmetic Quiz. Use integers to enter the answer!")
time.sleep(2)
operands1 = list(range(2, 12))
operators = ["+", "-", "x"]
operands2 = list(range(2, 12))
while question < 10:
operand1 = random.choice(operands1)
operand2 = random.choice(operands2)
operator = random.choice(operators)
user_answer = int(inputnumber('{} {} {} = '.format(operand1, operator, operand2)))
question += 1
Issues
First, you should declare function definitions outside of your script and call the function by identifier 'inputNumber()'
Also notice the slight change in Try/Except, and the PEP 8 Style Guide compliant formatting.
Related
This question already has answers here:
Asking the user for input until they give a valid response
(22 answers)
Why does my recursive function return None?
(4 answers)
Closed 9 months ago.
While creating a guess_the_number game in python, I wanted to catch the exception if user enters an invalid number, i.e. ValueError when typecasting the entered string to integer, I created a takeInput() function.
It works fine except for the part that when I raise an exception and enter a valid number after that, I get a TypeError.
import random
randInt = random.randint(1, 100)
count = 1
print("RandInt: " + str(randInt))
def takeInput(message):
userInput = input(message)
try:
userInput = int(userInput)
print("takeInput try " + str(userInput)) #This line is printing correct value every time
return userInput
except ValueError as e:
takeInput("Not a valid number, try again: ")
userInput = takeInput("Please enter a number: ")
while(not(userInput == randInt)):
print("while loop " + str(userInput)) #I am receiving a none value after I raise an exception and then enter a valid number
if(userInput < randInt):
userInput = takeInput("Too small, try again : ")
else:
userInput = takeInput("Too large, try again : ")
count += 1
print("Congratulations, you guessed it right in " + str(count) + " tries.")
You need to return the value of the function when an exception occurs. Since you're not returning anything, it returns None by default even when the function gets called.
def takeInput(message):
userInput = input(message)
try:
userInput = int(userInput)
print("takeInput try " + str(userInput)) #This line is printing correct value every time
return userInput
except ValueError as e:
return takeInput("Not a valid number, try again: ")
A few things unrelated to the error,
Try using snake_case and not camelCase in python.
f strings are pretty nice, print(f"takeInput try {userInput}")
Consider while userInput != randInt:
Please help me. I wanted the counter num variable to add everytime the function is ran. But its not working, please tell me why I did wrong. If I use return num then the code is ending which I dont want, but n =+1 is not working, please help. Thanks a lot.
def prompt():
num = 1
print(num)
question = input("Do you want to add a file(y,n): ")
if question == "y":
file = input("Which File?: ")
nukefile.append(file)
st_frm = input("Start frame: ")
start_frame.append(st_frm)
en_frm = input("End Frame: ")
end_frame.append(en_frm)
#return num + 1
num =+1
print(num)
nukew = str("start /wait Nuke11.1.exe -x -"+st_frm+"-"+en_frm+" "+file)
nukewrite.append(nukew)
que = (str(num)+". "+file+"--"+st_frm+","+en_frm)
for_artist.append(que)
for x in for_artist:
print(x)
prompt()
return num
elif question == "n":
print(nukewrite)
f = open(batchfile, "a")
for shotsa in nukewrite:
f.write('\n'+shotsa+'\n')
print("Following files will render:")
for shotsb in nukefile:
print(shotsb)
f.close()
else:
print("Invalid entry")
prompt()
If you want to count how many times the function runs and keep it recursive, you'll need to define prompt.num outside of prompt. You can define it under the function or use a decorator and define it above.
def prompt():
prompt.num += 1
your code
prompt.num = 0
I am trying to create a function that will receive input from a list and justify whether it is a float value or not, and if it is, continue with the program, and if it is not, ask the user to enter the answer a second time. The new value should go into the list at the same index as the previous, incorrect value.
For example, if somebody inputted into my code the value 'seventy-two' instead of 72, I want the inputHandler function to receive this incorrect value, tell the user that it is invalid, and ask the user to answer the same question again.
I want my function to use try-except-else statements. Here is my code:
QUIZ_GRADES = int(input("How many quiz grades? "))
PROGRAM_GRADES = int(input("How many program grades? "))
TESTS = int(input("How many tests? "))
def main():
globalConstantList = [QUIZ_GRADES, PROGRAM_GRADES, TESTS]
scoreList = []
returnedScoreList = getGrades(globalConstantList,scoreList)
returnedScoreValue = inputHandler(returnedScoreList)
returnedScoreValue2 = inputHandler(returnedScoreList)
returnedScoreListSum, returnedScoreListLength = totalList(returnedScoreList)
returnedScoreListAverage = calcAverage(returnedScoreListSum,
returnedScoreListLength)
returnedLetterGrade = determineGrade(returnedScoreListAverage)
userOutput(returnedScoreListAverage,returnedLetterGrade)
def getGrades(globalConstantList,scoreList):
for eachScore in globalConstantList:
#totalScoreList = 0.0
index = 0
for index in range(QUIZ_GRADES):
print("What is the score for", index + 1)
scoreList.append(float(input()))
index += 1
for index in range(PROGRAM_GRADES):
print("What is the score for", index + 1)
scoreList.append(float(input()))
index += 1
for index in range(TESTS):
print("What is the score for", index + 1)
scoreList.append(float(input()))
index += 1
return scoreList
def inputHandler(scoreList):
index = 0
try:
print("What is the score for", index + 1)
scoreList.append(float(input()))
return scoreList
except ValueError:
print("Your value is not correct. Try again.")
print("What is the score for", index + 1)
scoreList.append(float(input()))
return scoreList
def totalList(newScoreList):
returnedScoreListLength = len(newScoreList)
returnedScoreListSum = sum(newScoreList)
return returnedScoreListSum, returnedScoreListLength
def calcAverage(newScoreListSum, newScoreListLength):
returnedScoreListAverage = newScoreListSum / newScoreListLength
return returnedScoreListAverage
def determineGrade(newScoreListAverage):
if newScoreListAverage >= 90:
return 'A'
elif newScoreListAverage >= 80:
return 'B'
elif newScoreListAverage >= 70:
return 'C'
elif newScoreListAverage >= 60:
return 'D'
else:
return 'F'
def userOutput(newScoreListAverage, newLetterGrade):
print("Your overall grade is",format(newScoreListAverage,'.2f'))
print("Your letter grade is",newLetterGrade)
print()
main()
As far as I understand, you want to check an user's input and convert it to a float. If successful, you want to proceed, if not, you want to ask again.
Assuming this is the case, you might want to write a function which asks for user input, tries to convert input to float, and returns it if successful.
def input_float(prompt):
while True:
try:
inp = float(input(prompt))
return inp
except ValueError:
print('Invalid input. Try again.')
f = input_float('Enter a float')
print(f)
You can then use this snippet as a starting point for further handling of f (which is a float) the user provided.
You can check your number float or int or string using if elif statement then do your work in side the body of your code
num = input("Enter a number ")
if type(num ) == int : print "This number is an int"
elif type(num ) == float : print "This number is a float"
here you can use function to call this code again and again and place this code in that function and also use try bock to catch exception .
I have been trying to program a maths quiz that both works and is as efficient as possible. Looking over my code I saw I had a lot of integer inputs and that lead to me having the program to ask the question/exit the system if the criteria isn't met, so to help me I thought that it would be useful to create a new function. Here is my attempt:
def prompt_int(prompt=''):
while True:
if status == prompt_int(prompt=''):
val = input(prompt)
if val in (1,2):
return int(val)
return true
elif status != prompt_int(prompt=''):
val = input(prompt)
if val in (1,2,3):
return int(val)
return true
else:
print("Not a valid number, please try again")
However, when I try to implement this function around my code it doesn't work properly as it says that status isn't defined however, when I do define status it goes into a recursion loop. How can I fix this problem?
Here is my original code before i try to implement this function:
import sys
import random
def get_bool_input(prompt=''):
while True:
val = input(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
sys.exit("Not a valid input (yes/no is expected) please try again")
status = input("Are you a teacher or student? Press 1 if you are a student or 2 if you are a teacher")# Im tring to apply the new function here and other places that require integer inputs
if status == "1":
score=0
name=input("What is your name?")
print ("Alright",name,"welcome to your maths quiz."
"Remember to round all answer to 5 decimal places.")
level_of_difficulty = int(input(("What level of difficulty are you working at?\n"
"Press 1 for low, 2 for intermediate "
"or 3 for high\n")))
if level_of_difficulty not in (1,2,3):
sys.exit("That is not a valid level of difficulty, please try again")
if level_of_difficulty == 3:
ops = ['+', '-', '*', '/']
else:
ops = ['+', '-', '*']
for question_num in range(1, 11):
if level_of_difficulty == 1:
number_1 = random.randrange(1, 10)
number_2 = random.randrange(1, 10)
else:
number_1 = random.randrange(1, 20)
number_2 = random.randrange(1, 20)
operation = random.choice(ops)
maths = round(eval(str(number_1) + operation + str(number_2)),5)
print('\nQuestion number: {}'.format(question_num))
print ("The question is",number_1,operation,number_2)
answer = float(input("What is your answer: "))
if answer == maths:
print("Correct")
score = score + 1
else:
print ("Incorrect. The actual answer is",maths)
if score >5:
print("Well done you scored",score,"out of 10")
else:
print("Unfortunately you only scored",score,"out of 10. Better luck next time")
class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
while class_number not in ("1","2","3"):
print("That is not a valid class, unfortunately your score cannot be saved, please try again")
class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
else:
filename = (class_number + "txt")
with open(filename, 'a') as f:
f.write("\n" + str(name) + " scored " + str(score) + " on difficulty level " + str(level_of_difficulty))
with open(filename, 'a') as f:
f = open(filename, "r")
lines = [line for line in f if line.strip()]
f.close()
lines.sort()
if get_bool_input("Do you wish to view previous results for your class"):
for line in lines:
print (line)
else:
sys.exit("Thanks for taking part in the quiz, your teacher should discuss your score with you later")
if status == "2":
class_number = input("Which classes scores would you like to see? Press 1 for class 1, 2 for class 2 or 3 for class 3")
if class_number not in (1,2,3):
sys.exit("That is not a valid class")
filename = (class_number + "txt")
with open(filename, 'a') as f:
f = open(filename, "r")
lines = [line for line in f if line.strip()]
f.close()
lines.sort()
for line in lines:
print (line)
Well, just a part:
def prompt_int(prompt=""):
while True:
val = input(prompt)
if val in ("1", "2"):
return int(val), True
Will ask again and again. And return when the user enter "1" or "2"!
But better: "if val in "12":
def prompt_int(prompt=""):
while True:
val = input(prompt)
if val.isdigit():
return int(val)
Hi if you dont want to have valid values send to your you could change your code as the function above.
But you could also change it to do the system exits:
def prompt_int(prompt="", authorized=()):
while True:
val = raw_input(prompt)
if val.isdigit():
if int(val) in authorized:
return int(val)
else:
sys.exit("Bla bla bla too bad")
def prompt_int(prompt=''):
while True:
if status == prompt_int(prompt=''):
This line will look for the name "status" in the global namespace (module's namespace), and raise a NameError if there's no global variable named 'status'.
If there's one, it will then recursively calls prompt_int without any possible termination, resulting theoretically in an endless recursion, but practically (in CPython at least) in a RuntimeError when it will hit the maximum recursion depth.
There are also quite a few other things that won't work as you expect:
val = input(prompt)
if val in (1,2):
In Python 3.x, val will be a string, so it will never compare equal to an int. In Python 2.x, input() is a shortcut for eval(raw_input()), which might return an int, but is also a huge security flaw since it unconditionnally execute untrusted code.
return int(val)
return true
The second return statement will never be executed, obviously, since the function will exit at the first one.
A simpler implementation might look like this:
# rebinds raw_input to input for python < 3
import sys
if sys.version_info.major < 3:
input = raw_input
def prompt_int(prompt='', choices=None):
while True:
val = input(prompt)
try:
val = int(val)
if choices and val not in choices:
raise ValueError("{} is not in {}".format(val, choices))
return val
except (TypeError, ValueError) as e:
print(
"Not a valid number ({}), please try again".format(e)
)
While we're at it, there's room for improvement in other parts of your code. Let's start with this:
def get_bool_input(prompt=''):
while True:
val = input(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
sys.exit("Not a valid input (yes/no is expected) please try again")
First point: your naming is not consistent. If your other function is named prompt_int, this one should be named prompt_bool. Also, you have one function (prompt_int) looping forever and the other one exiting the whole program on invalid input, which is another inconsistency. If you want to allow the user to exit on any prompt, provide an explicit option for it, ie:
def prompt_bool(prompt, quit='Q'):
prompt += " (hit '{}' to exit) : ".format(quit)
while True:
val = input(prompt).strip().upper()
if val == quit:
sys.exit("Goodbye")
elif val == 'yes':
return True
elif val == 'no':
return False
else:
print "Invalid input '{}', please try again".format(val)
Of course you then want to provide the same option in prompt_int(), which leads to a more generic function:
def get_input_or_quit(prompt, quit="Q"):
prompt += " (hit '{}' to exit) : ".format(quit)
val = input(prompt).strip()
if val.upper() == quit:
sys.exit("Goodbye")
return val
def prompt_bool(prompt):
while True:
val = get_input_or_quit(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
print "Invalid input '{}', please try again".format(val)
And of course you also replace the call to input by a call to get_input_or_quit in prompt_int.
We could go on for long - splitting all your code in distinct, self-contained function, writing a "main()" function to drive them (instead of having the "main" part at the top level), and obviously using the operator module instead of eval().
I have the following code:
#AON = Amount of Numbers to average
def general():
print "Enter how many numbers you will enter."
print "Maximum amount is 10: "
aon = raw_input()
try:
aon = int(aon)
if aon >= 10:
print "I cannot average more than 10 numbers."
general()
else:
start_average()
except ValueError:
print "You entered an invalid input, try again."
general()
def start_average():
if aon == 1:
print "You cannot average one number."
general()
elif aon == 2:
def first_number():
print "First number: "
first_ni = raw_input()
second_number()
first_number()
def second_number():
print "Second number: "
second_ni = raw_input()
ans_two = first_ni / second_ni
second_number()
final_two()
elif aon == 3:
def third_number():
first_number()
second_number()
print "Third number: "
third_ni = raw_input()
ans_three = ans_two / third_ni
third_number()
final_three()
elif aon == 4:
def fourth_number():
first_number()
second_number()
third_number()
print "Fourth number: "
fourth_ni = raw_input()
ans_four = ans_three / fourth_ni
fourth_number()
final_four()
elif aon == 5:
def fifth_number():
first_number()
second_number()
third_number()
fourth_number()
print "Fifth number: "
fifth_ni = raw_input()
ans_five = ans_four / fifth_ni
fifth_number()
final_five
def final_two():
final_input = ans_two
final_answer()
def final_three():
final_input = ans_three
final_answer()
def final_four():
final_input = ans_four
final_answer
def final_five():
final_input = ans_five
final_answer()
def final_six():
final_input = ans_six
final_answer()
def final_seven():
final_input = ans_seven
final_answer()
def final_eight():
final_input = ans_eight
final_answer()
def final_nine():
final_input = ans_nine
final_answer()
def final_answer():
listofnumbers = [first_ni, second_ni, third_ni, fourth_ni, fifth_ni, sixth_ni, seventh_ni, eight_ni, ninth_ni]
print "The average of your numbers:"
print listofnumbers
print "Is = %d." % final_input
general()
It's purpose is to find the average of a number, but when I run it through PowerShell, I get the following error:
Traceback (most recent call last):
File "average.py", line 97, in <module>
general()
File "average.py", line 10, in general
general()
File "average.py", line 10, in general
general()
File "average.py", line 12, in general
start_average()
UnboundLocalError: local variable 'start_average' referenced before assignment
I've probably done this more throughout my code, and I just made this, but I just don't know how to fix it or what is the error showing! I don't understand.
It's hard to tell from what you've pasted, because you've clearly broken the indentation.
But it looks like this code:
print "Enter how many numbers you will enter."
print "Maximum amount is 10: "
… is meant to be inside general, while this code:
aon = raw_input()
try:
aon = int(aon)
if aon >= 10:
print "I cannot average more than 10 numbers."
general()
else:
start_average()
except ValueError:
print "You entered an invalid input, try again."
general()
… is meant to be at module level.
Code is executed in the order it appears. Function definitions are just code, like anything else. So, you can't call a function before you define it, because the function doesn't exist yet.
You're probably about to object, with an example like this:
def foo():
bar()
def bar():
print('Hi!')
foo()
It looks like we're calling bar before it exists, and yet it works. How?
Well, the definition of foo is being executed before bar exists, but that's fine. That just defines a function that will, when run, call whatever bar means. As long as we've defined bar before we call it—and we have—everything is fine.
However, you have a number of similar problems in your code. For example, let's look at this part:
elif aon == 2:
def first_number():
print "First number: "
first_ni = raw_input()
second_number()
first_number()
def second_number():
print "Second number: "
second_ni = raw_input()
ans_two = first_ni / second_ni
second_number()
final_two()
That first_ni is a local variable within the first_number function. Every time you call first_number, a new first_ni gets defined, but only visible within that function. You can't use it in second_number, because second_number can only see its own local variables, and global variables, and first_ni is neither.
The concept you need to understand is called scope. Python has some nice tools to help you understand scope. You can print out locals() and globals() and dir() at any part of your program to see what's in scope there. But you'll need to read the tutorial first.
Indentation and a few other things are questionable. I'm not sure why you're defining all of these functions inside of other functions... I think this will do what you want. You're going to need a lot more error checking though (making sure the inputs are integers, divide by 0, etc.)
>>> def getMean(maxNumsToDivide):
... listNums = []
... for i in range(maxNumsToDivide):
... num = raw_input("Please enter a number: ")
... if not num:
... break
... listNums.append(int(num))
... return float(sum(listNums))/len(listNums)
...
>>> getMean(100)
Please enter a number: 2
Please enter a number: 3
Please enter a number: 4
Please enter a number: 5
Please enter a number: 3
Please enter a number:
3.4