This question already has answers here:
Asking the user for input until they give a valid response
(22 answers)
Closed 8 years ago.
def p_parameter(p):
if p < 10 or p > 100:
int(input("Please try again: "))
newp = p
return newp
else:
newp <10 or newp >100
input("Good bye")
bye()
def main():
speed(0)
R=100
r=4
p=int(input("Please enter a number between 10 and 100: "))
p_parameter(p)
t_iter(R,r,p)
Xcord(R,r,p,t_iter(R,r,p))
Ycord(R,r,p,t_iter(R,r,p))
input("Hit enter to close porgram")
bye()
main()
Here is my code for a program which draws a spirograph. The program runs fine but what I have posted here is my attempt to have the user enter a value between 10-100 for p.
What I want to do is check to see if p is < 10 or p > 100. If it is, then give the user a chance to re-enter a new value of p and use that value as long as it fits the allowed limits. After the second check if the user still has entered an incorrect value of p I want the program to close.
The problem is that it checks for 'p' then asks for p again but it only take the first value of 'p', and does not preform the second check or give p its new value.
You should probably just prompt in the function. This is the standard idiom for writing these kinds of validations:
def validate():
while True:
# begin inf. loop
p = input("some prompt goes here")
if some_validation:
break
# end inf. loop
# therefore if the validation fails, it reprompts
# once you're out of the inf. loop...
return p
This is one of those things you could build a pretty good decorator for
def validate(validation, not_valid_warning=None):
if not hasattr(validation, '__call__'):
raise TypeError("validation must be callable")
def wrapper(f):
def wrapped(*args):
while True:
p = f(*args)
if validation(p):
break
if not_valid_warning:
print(not_valid_warning)
return p
return wrapped
return wrapper
#validate(lambda x: x < 10 or x > 100)
def v_input(*args):
return __builtins__.input(*args)
# Example..........
if __name__ == "__main__":
v_input("Enter a number less than 10 or more than 100: ")
Problems with your solution & Corrections:
it only take the first value of p and does not give p its new value.
you ask the user for p again, but do not assign this new value to newp variable, like so:
newp = int(input("Please try again: "))
does not preform the second check.
your else statement is checking for condition on newp outside the scope of the newp variable, which is inside the if statement. You should encapsulate your check on newp variable inside the if statement, like so:
def p_parameter(p):
if p < 10 or p > 100:
newp = int(input("Please try again: "))
if newp <10 or newp >100:
you don't have return statements inside the p_parameter() function for the instances when the program does not enter the if statement. So it should instead be like this:
def p_parameter(p):
if p < 10 or p > 100:
newp = int(input("Please try again: "))
if newp <10 or newp >100:
print( "Good Bye")
bye()
else:
return newp # need return statements like this
else:
return p # need return statements like this
Suggested Solution to your questions:
What I want to do is check to see if 'p' is < 10 or 'p' > 100, if it is then give the user a chance to reenter a new value of 'p' and use that value as long as it fits within the allowed parameters.
use a while True: infinite loop with the break statement to exit if the correct answer is received.
use try, except and else block with the ValueError
to catch any errors due to inputs that are not integers.
to detect any inputs that are out of the allowed range.
After the second check if the user still has entered an incorrect value of 'p' I want the program to close.
In order to close the program, you can either:
let the user hit ctrl+c (my personal preference), or
put a counter of how many times the while loop should be run to check for new input, and then force the program to exit if a limit is reached by using sys.exit(0) (Note: First You'll need to import sys to use it; I think your bye() is doing just that).
Putting it all together:
In your main() function, remove the input() statement and only have a call to p_parameter() function, like so:
p = p_parameter()
Define p_parameter() function as follows:
import sys
def p_parameter():
exit_counter = 1 # counter to exit after 2 tries
while True:
try:
p = int( input( "Please enter a number between 10 and 100: ") )
except ValueError:
print( "Not a number, Try Again" )
else:
if 10 < p < 100: # this is much faster than your approach
break # exit the loop
else:
print( "Value not in range")
# increment counter to exit when 2 tries are over
exit_counter+=1
if ( counter > 2 ):
print( "Good Bye" )
sys.exit(0) # bye()
return p
Related
I have this assignment to create a program that asks user to input any positive integer repeatedly or type anything else to end and generate the sum, count and average of the numbers. My teacher wants all the code in these this structure with these three def’s only
This is the code I have, any suggestions on how to get it to work?
def calcAverage(total,count):
sum = 0
count = 0
average = sum / count
def inputNumber(message):
while True:
try:
userInput = int(input(message))
count = count + 1
sum = sum + entry
if userInput < 0:
raise ValueError
except ValueError:
main()
else:
return userInput
break
entry = inputNumber('Type any positive integer, anything else to quit')
def main():
print('Sum')
print(sum)
print('Average')
print(average)
print('Total Numbers')
print(count)
The question is not well explained + we don't really get what the boundaries are. Moreover, you should clearly state what is not working. Now, to give you some hint, this is how I would do it:
input = None
L = list()
while True:
try:
input = int(input('Type any positive integer, anything else to quit: '))
if input < 0:
break
else:
L.append(input)
except:
break
S = sum(L)
I think you don't need to use exceptions here. Condition statements would make it clearer.
I would put the valid inputs in a list until the user make a invalid input. When it happens, just get out of your while loop using a break statement and return the result.
I want to write a program with this logic.
A value is presented of the user.
Commence a loop
Wait for user input
If the user enters the displayed value less 13 then
Display the value entered by the user and go to top of loop.
Otherwise exit the loop
You just need two while loops. One that keeps the main program going forever, and another that breaks and resets the value of a once an answer is wrong.
while True:
a = 2363
not_wrong = True
while not_wrong:
their_response = int(raw_input("What is the value of {} - 13?".format(a)))
if their_response == (a - 13):
a = a -13
else:
not_wrong = False
Although you're supposed to show your attempt at coding towards a solution and posting when you encounter a problem, you could do something like the following:
a = 2363
b = 13
while True:
try:
c = int(input('Subtract {0} from {1}: '.format(b, a))
except ValueError:
print('Please enter an integer.')
continue
if a-b == c:
a = a-b
else:
print('Incorrect. Restarting...')
a = 2363
# break
(use raw_input instead of input if you're using Python2)
This creates an infinite loop that will try to convert the input into an integer (or print a statement pleading for the correct input type), and then use logic to check if a-b == c. If so, we set the value of a to this new value a-b. Otherwise, we restart the loop. You can uncomment the break command if you don't want an infinite loop.
Your logic is correct, might want to look into while loop, and input. While loops keeps going until a condition is met:
while (condition):
# will keep doing something here until condition is met
Example of while loop:
x = 10
while x >= 0:
x -= 1
print(x)
This will print x until it hits 0 so the output would be 9 8 7 6 5 4 3 2 1 0 in new lines on console.
input allows the user to enter stuff from console:
x = input("Enter your answer: ")
This will prompt the user to "Enter your answer: " and store what ever value user enter into the variable x. (Variable meaning like a container or a box)
Put it all together and you get something like:
a = 2363 #change to what you want to start with
b = 13 #change to minus from a
while a-b > 0: #keeps going until if a-b is a negative number
print("%d - %d = ?" %(a, b)) #asks the question
user_input = int(input("Enter your answer: ")) #gets a user input and change it from string type to int type so we can compare it
if (a-b) == user_input: #compares the answer to our answer
print("Correct answer!")
a -= b #changes a to be new value
else:
print("Wrong answer")
print("All done!")
Now this program stops at a = 7 because I don't know if you wanted to keep going with negative number. If you do just edited the condition of the while loop. I'm sure you can manage that.
I know I can't use Goto and I know Goto is not the answer. I've read similar questions, but I just can't figure out a way to solve my problem.
So, I'm writing a program, in which you have to guess a number. This is an extract of the part I have problems:
x = random.randint(0,100)
#I want to put a label here
y = int(raw_input("Guess the number between 1 and 100: "))
if isinstance( y, int ):
while y != x:
if y > x:
y = int(raw_input("Wrong! Try a LOWER number: "))
else:
y = int(raw_input("Wrong! Try a HIGHER number "))
else:
print "Try using a integer number"
#And Here I want to put a kind of "goto label"`
What would you do?
There are lots of ways to do this, but generally you'll want to use loops, and you may want to explore break and continue. Here's one possible solution:
import random
x = random.randint(1, 100)
prompt = "Guess the number between 1 and 100: "
while True:
try:
y = int(raw_input(prompt))
except ValueError:
print "Please enter an integer."
continue
if y > x:
prompt = "Wrong! Try a LOWER number: "
elif y < x:
prompt = "Wrong! Try a HIGHER number: "
else:
print "Correct!"
break
continue jumps to the next iteration of the loop, and break terminates the loop altogether.
(Also note that I wrapped int(raw_input(...)) in a try/except to handle the case where the user didn't enter an integer. In your code, not entering an integer would just result in an exception. I changed the 0 to a 1 in the randint call too, since based on the text you're printing, you intended to pick between 1 and 100, not 0 and 100.)
Python does not support goto or anything equivalent.
You should think about how you can structure your program using the tools python does offer you. It seems like you need to use a loop to accomplish your desired logic. You should check out the control flow page for more information.
x = random.randint(0,100)
correct = False
prompt = "Guess the number between 1 and 100: "
while not correct:
y = int(raw_input(prompt))
if isinstance(y, int):
if y == x:
correct = True
elif y > x:
prompt = "Wrong! Try a LOWER number: "
elif y < x:
prompt = "Wrong! Try a HIGHER number "
else:
print "Try using a integer number"
In many other cases, you'll want to use a function to handle the logic you want to use a goto statement for.
You can use infinite loop, and also explicit break if necessary.
x = random.randint(0,100)
#I want to put a label here
while(True):
y = int(raw_input("Guess the number between 1 and 100: "))
if isinstance( y, int ):
while y != x:
if y > x:
y = int(raw_input("Wrong! Try a LOWER number: "))
else:
y = int(raw_input("Wrong! Try a HIGHER number "))
else:
print "Try using a integer number"
# can put a max_try limit and break
I need to limit the number of invalid inputs allowed so that after the given amount of tries the program exits.
Invalid is defined by the input being less than zero.
The number of attempts let say is 3.
def number():
number = float(input('please enter a number (must be greater thatn zero): '))
if number >= 0 :
print ('you choose number:', number)
else:
print ('invalid input')
return
number()
How would I limit the number of invalid input attempts and make it so that the code would return to asking the question again and prompt for input but still keep track of previous attempts?
You have to use a loop, in this case a while loop will be convinient. You have to declare a variable invalid_attempts to keep the count of how many invalid inputs the user has given.
The condition to finish the loop will be when invalid_attempts, which is increased when you get an invalid input, is greater or equal to 3. You may want to change 3 to fit your requirements:
def get_input():
invalid_attempts = 0
while invalid_attempts < 3:
number = float(input('please enter a number (must be greater thatn zero): '))
if number >= 0 :
print ('you choose number:', number)
return number # so you can call the method as 'some_variable = get_input()'
else:
print ('invalid input')
invalid_attempts += 1
Note: Since number is the name of the method, you shouldn't call a variable inside with the same name (because if you do, you won't be able to use that function inside, if it's necessary), in this case I'm calling the method get_input.
Use whilie loop before number = ..., for instance:
count = 0
while count < 3:
# do rest of the stuffs
count += 1
Actually, I think a for loop looks nicer:
for retry in range(5): # number of retries
try:
choice = float(input('please enter a number (must be greater thatn zero): '))
except ValueError:
print('Please enter an actual number')
continue
if choice >= 0:
print('You chose ', choice)
break
else:
print('Number must be >= 0')
continue
else:
print('Too many failures: be more cooperative')
(This is called a for-else construct; the else runs only if the for loop did not break).
You can also do it slightly more elegantly using recursion:
def get_number(max_tries, count = 0)
if count < max_tries:
valid_input = False
number = 0
try:
number = float(input('Please enter a number > 0'))
if number > 0:
valid_input = True
except:
pass
if valid_input:
return number
else:
return get_numbers(max_tries, count+1)
else:
print('Sorry, Too many Tries!)
return None
Whether you use a while loop or recursion is usually a matter of taste. They're functionally equivalent in many situations, of which this is on. This example also accounts for what happens if the user enters something that isn't a number, which will cause the float cast to throw.
Update:
To clarify a question asked by the OP:
def get_numbers(max_tries, count = 0)
Defines a function get_numbers, which takes two inputs, max_tries and count. count is given a default value, count = 0, which means if you call the function without specifying the count parameter, it will automatically assign it to be 0. max_tries is left without a default value, meaning you need to specify it every time you call the function or python will throw an error. If you usually have the same number of maximum tries, you could also assign this a default value, which would allow you to simply do number = get_numbers() and have it work as expected.
Recursion, to over-simplify, is basically when a function calls itself during its execution. Let's assume we did the following:
number = get_number(10)
And the user enters -1, which will cause the code to reach:
else:
return get_numbers(max_tries, count+1)
Since we said get_numbers(10), max_tries = 10, and count = 0, so this line becomes:
else:
return get_numbers(10, 1)
This causes the function to return the result of calling get_numbers again. Eventually the user will either enter valid input, or count > max_tries, which will cause the function to finally return a value.
Read the wiki I liked to, recursion is hard to explain without drawing it, but hopefully that helps.
If the player types in any out of range or invalid values, I want it to loop back to ask him to place his bet again.
I can get this half-way working when I wrap raw_input with int().
However, if say the player accidentally typed a letter or just hit enter without typing anything, it would throw an error, thus stopping the game/script.
So if a player does make a mistake like that, I need it to loop back to "Place your bet" again instead of throwing an error and crashing the script.
def betAmount():
if number_of_hands == 1:
if chip_count_player1 > 0:
global chips_bet
chips_bet = raw_input("Place your bet!")
if chips_bet in range(0, chip_count_player1 + 1):
print "Your bet is within range"
else:
print "NOT IN RANGE"
betAmount()
You need to convert the chips_bet to a number like this
try:
chips_bet = int(raw_input("Place your bet!"))
except ValueError:
betAmount()
You are constructing a new list of numbers and then checking if the chips_bet is there in it or not. That is inefficient. You can check like this
if 0 <= chips_bet <= chip_count_player1:
The base idea can be implemented like this
bet = getBet()
...
def getBet(maximum):
bet = -1
while (bet < 0) or (bet > maximum):
try:
bet = int(raw_input("Place your bet!"))
except ValueError: pass
return bet
you can split your prompt/input/validate loop into a little function, and just call that (it's easier to separate the retry loop from the program logic)
For example, this won't throw, and will only return a validated number:
def safe_int_input(prompt, validate):
while True:
try:
val = int(raw_input(prompt))
if validate(val):
return val
except: pass
print "invalid input"
and you'd call it like this:
chips_bet = safe_int_input("Place your bet! ",
lambda v:(v >= 0 and v <= chip_count_player1))