I have this function below, which I have done something wrong in somewhere.
def quantityFunction(product):
valid = False
while True:
if product is not None:
quantity = input("Please enter the amount of this item you would like to purchase: ")
for i in quantity:
try:
int(i)
return int(quantity)
valid = True
except ValueError:
print("We didn't recognise that number. Please try again.")
#If I get here, I want to loop back to the start of this function
return True
return False
To run through, the function is called from the main part of the program like so: quantity = quantityFunction(product)
The return False at the bottom of the code is to do with if product is None, which is needed after a bit of code in another function but has had to go in this function.
If the user input for quantity is a number, all works fine. If it is anything else, the Value Error is printed and you can enter another input. If you put another letter etc in, it repeats again, if you put a number in, it accepts it.
However, it does not return the number you inputted after the letters. It just returns 0.
I suspect this is something to do with how I am repeating the code, i.e. the code should loop back to the start of the function if it hits the Value Error.
Any Ideas?
You said:
the code should loop back to the start of the function if it hits the Value Error.
Then you should not use return statements, otherwise the function will terminate, returning True or False.
Few issue:
1) return statement returns control to the calling function.
2) You are looping over the input, which is wrong.
3) valid=True isn't executed at all.
def quantityFunction(product):
valid = False
while True:
if product is not None:
quantity = raw_input("Please enter the amount of this item you would like to purchase: ")
try:
return int(quantity)
#valid = True (since it is never run)
except ValueError:
print("We didn't recognise that number. Please try again.")
#If I get here, I want to loop back to the start of this function
#return True
return False
quantityFunction("val")
Note : Use raw_input() in case of Python 2.7 and input() in case of 3.x
Try this (some formatting included too, but the functionality should be the same):
def determine_quantity(product): # descriptive function name
if not product: # avoiding nesting
return False
while True:
quantity = input("Please enter the amount of this item you would like to purchase: ")
try:
return int(quantity) # try to convert quantity straight away
except ValueError:
print("We didn't recognise that number. Please try again.")
# nothing here means we simply continue in the while loop
Ideally, you'd take product out. A function should do as little as possible, and this check is better off somewhere else.
def determine_quantity():
while True:
quantity = input("Please enter the amount of this item you would like to purchase: ")
try:
return int(quantity)
except ValueError:
print("We didn't recognise that number. Please try again.")
First, let's address the code. Simply stated, you want a function that will loop until the user enters a legal quantity.
product doesn't do much for the function; check it in the calling program, not here. Let the function have a single purpose: fetch a valid quantity.
Let's work from there in the standard recipe for "loop until good input". Very simply, it looks like:
Get first input
Until input is valid
... print warning message and get a new value.
In code, it looks like this.
def get_quantity():
quantity_str = input("Please enter the amount of this item you would like to purchase: ")
while not quantity_str.isdigit():
print("We didn't recognise that number. Please try again.")
quantity_str = input("Please enter the amount of this item you would like to purchase: ")
return quantity
As for coding practice ...
Develop incrementally: write a few lines of code to add one feature to what you have. Debug that. Get it working before you add more.
Learn your language features. In the code you've posted, you misuse for, in, return, and a function call.
Look up how to solve simple problems. try/except is a more difficult concept to handle than the simple isdigit.
You should try this..
def quantityFunction(product):
valid = False
while True:
if product is not None:
quantity = raw_input("Please enter the amount of this item you would like to purchase: ")
if quantity.isdigit():
return int(quantity)
valid = True
else:
print("We didn't recognise that number. Please try again.")
continue
return False
quantity = quantityFunction("myproduct")
Related
Im currently working on a project for my coding class. The prompt is to make an atm interface.
All of my code is currently working but when it comes to the function of deposit() it asks for a whole number to be entered where I use int(input) say someone inputs a float like 45346.4 it comes up with an error. Is there a fix to this?
here is my code currently for the deposit function. The balance is already given outside of this function.
def deposit():
balanced = balance
print(f'Your current balance is ${balanced}\n------------------------------')
print('How much money would you like to deposit?\n---------------------------\n You can only deposit in whole numbers')
deposit_amount = int(input('Enter here:'))
if deposit_amount.is_integer():
balance_a_d = balanced + deposit_amount
print(f'You Current Balance is ${balance_a_d}\n-------------------------------\nHave a great day!')
quit()
else:
print('----------------------------\nThat is not a whole number please try again\n----------------------------')
deposit()
You could use a while loop and a try block to keep asking for input until ValueError is no longer raised.
Something like this:
number = None
while number == None:
try:
number = int(input('Enter here:'))
except ValueError as e:
print('Please enter a whole number.')
I have a general purpose input function which is simple to use and saves a lot of repeated code.
def getInput(prompt, t=str):
while True:
v = input(f'{prompt}: ')
try:
return t(v)
except ValueError:
print('Invalid input')
If I just want text input then:
getInput('Enter some text')
Of course, for plain text, this isn't really necessary.
If I want a float then:
getInput('Enter a float', float)
Or int:
getInput('Enter an integer', int)
This saves you from having to "wrap" all your inputs in try/except as it's all handled for you
I'm trying to write a program to calculate densities, and I have tried to create a while loop the prevents the user from entering nothing or a non-number for the volume.
But when I run the program the it just loops "You have to type a value" forever. I've tried the same code in a for loop and it does work after inputing 2 numbers.
def GetVolume():
print("How many cublic cm of water does the item displace")
Volume = input()
while Volume == ("") or type(Volume) != int:
print("You have to type a value")
Volume = input()
return float(Volume)
This solution is written assuming you are using Python 3. The problem in your code is that you are assuming that if you type in a number, the input method will return a type int. This is incorrect. You will always get a string back from your input.
Furthermore, if you try to cast int around your input to force an int, your code will raise if you enter a string, with:
ValueError: invalid literal for int() with base 10:
So, what I suggest you do to make your implementation easier is to make use of try/exceptinstead to attempt to convert your value to a float. If it does not work, you prompt the user to keep entering a value until they do. Then you simply break your loop and return your number, type casted to a float.
Furthermore, because of the use of the try/except, you no longer need to put in a conditional check in your while loop. You simply can set your loop to while True and then break once you have satisfied your condition in your code.
Observe the code below re-written with what I mentioned above:
def GetVolume():
print("How many cublic cm of water does the item displace")
Volume = input()
while True:
try:
Volume = float(Volume)
break
except:
print("You have to type a value")
Volume = input()
return Volume
def GetVolume():
Volume = input("How many cublic cm of water does the item displace")
while not Volume.replace('.', '').replace(',', '').isdigit():
Volume = input("You have to type a value")
return float(Volume)
x = GetVolume()
print(x)
You have to modify your while because is validating that is str or different than int. An input will always be an str by default unless you modified the type with int() or float() in your case.
You can use 'try' instead to check for this:
while True:
x = input("How many cubic cm of water does the item displace")
try:
x = float(x)
break
except ValueError:
pass
print('out of loop')
I am very new to Python (started 2 days ago). I was trying to validate positive integers. The code does validate the numbers but it asks twice after a wrong input is entered. For example if I enter the word Python, it says: This is not an integer! like is supposed to but if I enter 20 afterwards, it also says it is not an integer and if I enter 20 again it reads it.
def is_positive_integer(input):
#error: when a non-integer is input and then an integer is input it takes two tries to read the integer
flag = 0
while flag != 1:
try:
input = int(input)
if input <= 0:
print "This is not a positive integer!"
input = raw_input("Enter the number again:")
except ValueError:
print "This is not an integer!"
input = raw_input("Enter the number again: ")
if isinstance(input, int):
flag = 1
return input
number = raw_input("Enter the number to be expanded: ")
is_positive_integer(number)
number = int(is_positive_integer(number))
Any help is appreciated.
The main bug is that you call is_positive_integer(number) twice with the same input (the first thing you enter).
The first time you call is_positive_integer(number), you throw away the return value. Only the second time do you assign the result to number.
You can "fix" your program by removing the line with just is_positive_integer(number) on its own.
However, your code is a little messy, and the name is_positive_integer does not describe what the function actually does.
I would refactor a little like this:
def input_positive_integer(prompt):
input = raw_input(prompt)
while True:
try:
input = int(input)
if input <= 0:
print "This is not a positive integer!"
else:
return input
except ValueError:
print "This is not an integer!"
input = raw_input("Enter the number again: ")
number = input_positive_integer("Enter the number to be expanded: ")
The problem stems from the fact that you're calling is_positive_integer twice. So, the first time it's called, you send it a string like 'hello', then it says it's not an integer and tells you to try again. Then you enter '20', which parses fine, and it's returned.
But then you don't save a reference to that, so it goes nowhere.
Then you call the function again, this time saving a reference to it, and it first tries the original bad string, which was still there in number. Then it complains that it's a bad input, asks you for a new one, and you provide it, terminating the program.
I am trying to analyse user input and only allow integers to be inputted. I have succesfully managed to only allow denominations of 100s between a certain range, but I cannot work out how to prompt the user to re-enter data if they enter a random string.
Trying to use the "try" command just results in the program getting stuck:
while True:
try:
bet=int(raw_input('Place your bets please:'))
except ValueError:
print 'l2type'
#The following receives a betting amount from the user, and then assesses whether it is a legal bet or not. If not, the user is prompted to enter a legal bet.
while True:
if bet%100==0 and 100<=bet<=20000:
print bet,"Your bet has been accepted, can you make a million?"
break
else:
print bet,"Please enter a legal bet. The table minimum is 100, with a maximum of 20000 in increments of 100."
bet = input('Place your bets please:')
You have the right approach for rejecting non-integer input, but you need to break out of the loop if your user enters valid input. Use the break statement:
while True:
try:
bet=int(raw_input('Place your bets please:'))
break # we only get here if the input was parsed successfully
except ValueError:
print 'l2type'
You will probably also want to move the range checks within the loop. If input that's out of range doesn't naturally lead to an exception, use if statements to make sure "break" is only executed if the input is completely valid.
I rather prefer my recursive version:
def ask_bet(prompt):
bet = raw_input(prompt)
# Validation. If the input is invalid, call itself recursively.
try:
bet = int(bet)
except ValueError:
return ask_bet('Huh? ')
if bet % 100 != 0:
return ask_bet('Huh? ')
if not 100 <= bet <= 20000:
return ask_bet('Huh? ')
# The input is fine so return it.
return bet
ask_bet("Place your bets please: ")
In my opinion, that is much cleaner and easier to read than while loops. You don't have to bother what are attribute values after the first iteration? Adding new validation rules is also really simple.
Generally, I try to avoid while loop in favour of recursive version. Of course, not all the time, since it's slower and the stack is not infinite.
The problem here is that I just cant get python to check if Currency1 is in string, and if its not then print that there is an error,but if Currency1 IS in string then move on and ask the user to input Currency2, and then check it again.
You can use try-except:
def get_currency(msg):
curr = input(msg)
try:
float(curr)
print('You must enter text. Numerical values are not accepted at this stage')
return get_currency(msg) #ask for input again
except:
return curr #valid input, return the currency name
curr1=get_currency('Please enter the currency you would like to convert:')
curr2=get_currency('Please enter the currency you would like to convert into:')
ExRate = float(input('Please enter the exchange rate in the order of, 1 '+curr1+' = '+curr2))
Amount = float(input('Please enter the amount you would like to convert:'))
print (Amount*ExRate)
output:
$ python3 foo.py
Please enter the currency you would like to convert:123
You must enter text. Numerical values are not accepted at this stage
Please enter the currency you would like to convert:rupee
Please enter the currency you would like to convert into:100
You must enter text. Numerical values are not accepted at this stage
Please enter the currency you would like to convert into:dollar
Please enter the exchange rate in the order of, 1 rupee = dollar 50
Please enter the amount you would like to convert: 10
500.0
You were actually trying for:
if type(Currency1) in (float, int):
...
but isinstance is better here:
if isinstance(Currency1,(float,int)):
...
or even better, you can use the numbers.Number abstract-base class:
import numbers
if isinstance(Currency1,numbers.Number):
Although ... Currency1 = str(raw_input(...)) will guarantee that Currency1 is a string (not an integer or float). Actually, raw_input makes that guarantee and the extra str here is just redundant :-).
If you want a function to check if a string can be converted to a number, then I think the easiest way would be to just try it and see:
def is_float_or_int(s):
try:
float(s)
return True
except ValueError:
return False