I'm trying to make a very basic calculator to familiarize myself with the basics of python. Part of the code involves asking for inputs and setting those as different variables, but the variables put in as inputs are stored as strings, even though they're entered as numbers:
def change_x_a():
velocity_i = input("Initial Velocity?")
velocity_f = input("Final Velocity?")
time = input("Time?")
float(velocity_i)
float(velocity_f)
float(time)
answer = (0.5*(velocity_i+velocity_f)*time)
print(answer)
Is there a fix for this?
float() doesn't modify the variable you pass it. Instead, it converts the value you give it and returns a float.
So
float(velocity_i)
by itself does nothing, where
velocity_i = float(velocity_i)
will give the behavior you're looking for.
Keep in mind that float() (and the other type-conversion functions) will throw an exception if you pass them something they're not expecting. For a better user experience, you should handle these exceptions1. Typically, one does this in a loop:
while True:
try:
velocity_i = float(input("Initial Velocity?"))
break # Valid input - stop asking
except ValueError:
pass # Ignore the exception, and ask again
We can wrap this behavior up into a nice little function to make it more re-usable:
def get_input(prompt, exptype):
while True:
try:
return exptype( input(prompt) )
except ValueError:
pass # Ignore the exception, and ask again
and call it like this:
val_f = get_input('Give me a floating-point value:', float)
val_i = get_input('Give me an integer value:', int)
1 - Wow, I just realized that I independently wrote almost the exact same code as the Python tutorial, which I linked to, after the fact.
You can convert the inputs to float when you take them from the user.
Try
velocity_i = float(input("Initial Velocity?")
And so on.
Yes. Simply convert it to a float:
velocity_i = float(input("Initial Velocity?"))
or an integer:
velocity_f = int(input("Final velocity?"))
Related
I have a command line console game where I'm trying to capture integers from the User (the game is for learning times tables). I built a re-usable function to handle this which is working for blank answers, however will break if the User enters a string (e.g. "abc").
Can someone help me extend this function to filter out strings as well? (e.g. they should be asked to enter a number). I believe the error is being caused by the casting of int() in the return statement, however I need the input to be an Int for answer-checking comparison purposes (e.g. I compare their input to a stored answer, for which I need an Int == Int comparitor).
Function:
# gets a non-blank int from the User, printing a prompt and optionally displaying an error prompt
def get_int(prompt, err_prompt):
input_int = ""
# if entry is blank
while not input_int:
try:
# enter input
input_int = input(prompt)
if not input_int:
raise ValueError(err_prompt)
except ValueError as err:
print(err)
return int(input_int)
Calling the function example:
# get a non-blank int from the User as a guess
# note 'current_q' is a string from a list, e.g. "2 x 2 = " which acts as the prompt
guess = get_int(current_q, "You don't have a lot of other options. Try guessing a number...\n")
Example of the code working for blank answers:
Example of the code not working for strings:
Your if statement is wrong here:
if not input_int:
raise ValueError(err_prompt)
It will not raise an error if the value is not an empty string since its 'truthy'.
Instead you need to manually convert the input to an int and catch error:
def get_int(prompt, err_prompt):
input_int = ""
# if entry is blank
while not input_int:
try:
input_int = int(input(prompt)) # convert input to int
except ValueError:
print(err_prompt) # if the value can't be converted simply print your existing error prompt
return input_int
You could use isdigit on the input to check if it's an int before you cast it.
def get_int(prompt:str, error:str):
while not (u:=input(prompt)).isdigit():
print(error)
return int(u)
I am writing a code which should use only def (). input() cannot be used inside def(). When a numeric value is passed, it is okay. When string (e.g. Five, ten, etc.) is provided, it returns NameError. How to fix this issue using try and except.
def num(n):
try:
return int(n)
except NameError:
print('Error: Enter numeric nalue')
return
num(Five)
output: NameError: name 'Five' is not defined
I am using Anaconda 2020.2 (Python3.7.6 64-bit)
Two issues:
When you are trying to test your routine with a string value, you are trying to code the string constant without the quotes, so that it is instead trying to look up the non-existent variable Five, hence the NameError. You need quotes around it (i.e. 'Five').
Inside your function, the relevant exception to look for in the case of non-numeric data is a ValueError.
Example with these corrected:
def num(n):
try:
return int(n)
except ValueError:
print('Error: Enter numeric value')
return
print(num('Five'))
below
(the idea is to return a tuple from the function call. first tuple element is a boolean that tells if we have a valid int. second tuple element can be the actual int or a string that explains why we cant convert the input to int)
def to_int(val):
try:
result = int(val)
return True,result
except ValueError:
return False,'{} is not a valid integer'.format(val)
print(to_int(7))
print(to_int('ttt'))
output
(True, 7)
(False, 'ttt is not a valid integer')
Try this :
def num(n):
try :
return int(n)
except:
raise NameError("Please provide an integer value")
num('five')
lets say i'm showing some data to user , i want user to be able to perform some sort of filtering on a numeric field in the database using a GET form so i have something like this
code = request.GET.get('code')
condition = {}
if( code is not None and int(code) > 0 ):
condition['code'] = int(code)
Somemodel.objects.filter(**condition)
but this works only if i code contains a number otherwise i get this error
invalid literal for int() with base 10: ''
so what is the pythonic way to handle this problem ? should i use try/except block? i perfer to handle this in the same if statement considering i might add other filters
isnumeric could check if code can be cast to int and also check that code is positive (when converted to an integer) thus replacing int(code) > 0:
if code is not None and code.isnumeric():
condition['code'] = int(code)
You should use a Django form with one or more IntegerFields; they do this conversion for you, then you can get the result from cleaned_data.
This function convert GET params to python numeric/bool accordingly:
def convert_params_to_int_or_bool(params):
for k, v in params.items():
if v.isnumeric():
params[k] = int(v)
if v == 'false':
params[k] = False
if v == 'true':
params[k] = True
The reason you are getting this error because int() expects the value in number it can be in the form string but it should be a number like "22","33" etc are valid .
But in your case you are passing empty that's why its raising an error. You can achieve your desired output using type(), it helps you in checking the type of number
So the modified code is
code = request.GET.get('code')
condition = {}
if( code is not None and type(code) == int ):
condition['code'] = int(code)
Somemodel.objects.filter(**condition)
Hope it helps :)
I am completely new to python and programming but I am trying to learn it using more practical approach.
What I am trying to do is an exercise for converting different units, e.g. pounds -> kilograms, foot -> meter etc.
I have defined all the functions for different unit pairs:
def kg_to_g(value):
return round(value*1000.0,2)
def g_to_kg(value):
return round(value/1000.0,2)
def inch_to_cm(value):
return round(value*2.54,2)
def cm_to_inch(value):
return round(value/2.54,2)
def ft_to_cm(value):
return round(value*30.48,2)
etc.
and created a list with names of these functions:
unit_list = ['kg_to_g','g_to_kg','inch_to_cm','cm_to_inch',
'ft_to_cm','cm_to_ft','yard_to_m','m_to_yard',
'mile_to_km','km_to_mile','oz_to_g','g_to_oz',
'pound_to_kg','kg_to_pound','stone_to_kg','kg_to_stone',
'pint_to_l','l_to_pint','quart_to_l','l_to_quart',
'gal_to_l','l_to_gal','bar_to_l','l_to_bar']
The program should randomly choose a unit pair(e.g. kg->pounds) and value (e.g. 134.23), and the user will be asked to convert those values.
random_unit = random.choice(unit_list)
lower = 0.1001
upper = 2000.1001
range_width = upper - lower
ranval = round(random.random() * range_width + lower, 2)
When user enters answer, the program should compare answer with the calculations defined by function and tell user if it is a correct answer or wrong answer:
def input_handler(answer):
if answer == random_unit(ranval):
label2.set_text("Correct!")
else:
label2.set_text("Wrong!")
Unfortunately, that way program doesn't work, and codesculptor(codesculptor.org) returns with an error
TypeError: 'str' object is not callable
Could someone please explain to me what is wrong with the code and suggest something to solve the problem.
Because you've enclosed the function names (in the list) in quotes, they have become strings.
Change your list to:
unit_list = [kg_to_g, g_to_kg, inch_to_cm, cm_to_inch,
ft_to_cm, cm_to_ft, yard_to_m, m_to_yard,
mile_to_km, km_to_mile, oz_to_g, g_to_oz,
pound_to_kg, kg_to_pound, stone_to_kg, kg_to_stone,
pint_to_l, l_to_pint, quart_to_l, l_to_quart,
gal_to_l, l_to_gal, bar_to_l, l_to_bar]
And now it is a list of functions, which can be called like this: unit_list[0](34), for example.
So now random_unit(ranval) should not throw an exception.
Note also that comparing floats (if answer == random_unit(ranval)) will most likely cause you problems. See Is floating point math broken? for some detailed explanations of why this is.
As you are rounding you may get away with it, but it's good to be aware of this and understand that you need to deal with it in your code.
I think this is what you are asking about. You should be able to store the functions in a list like this
unit_list = [kg_to_g, g_to_kg, inch_to_cm, cm_to_inch, ft_to_cm]
You can then call each item in the list and give it a parameter and it should execute the function for example like this:
unit_list[0](value)
I'm making a basic BMI calculation program for a class assignment using TKinter for the GUI, and ran into a problem when trying to validate the user's input.
I'm trying to only allow numerical input and to deactivate the 'calculate' button and send an error message when the user enters anything that's not a number. However, at the minute it will throw up an error for a single digit number (e.g. 2) but will accept multiple digits (e.g. 23). I'm quite new to this so could you please explain why this is happening, or if there's a better way to write this?
Here are the relevant parts of my code:
#calculate button
cal = ttk.Button(main, text = 'Calculate!')
cal.grid(row = 4, column = 2)
#height entry box
hb = tk.Entry(main, textvariable = height)
hb.grid(row = 2, column = 2)
hb.bind('<Key>', lambda event: val(hb.get()))
#validation error message
vrs = tk.Label(main, text = 'Please enter a number in the box')
vrs.grid(row = 8, column = 2)
#so that its position is saved but won't appear until validation fails
vrs.grid_remove()
#validation function
def val(value):
if value.isdigit():
print('valid')
vrs.grid_remove()
cal.state(['!disabled'])
else:
print('invalid')
vrs.grid()
cal.state(['disabled'])
Thanks in advance for your help.
The first thing you should do to debug this is to print out value inside of val, to see if your assumptions are correct. Validating your assumptions is always the first step in debugging.
What you'll find is that your function is being called before the digit typed by the user is actually inserted into the widget. This is expected behavior.
The simple solution is to put your binding on <KeyRelease>, since the default behavior of inserting the character is on <KeyPress>:
hb.bind('<Any-KeyRelease>', lambda event: val(hb.get()))
Even better would be to use the Entry widget's built-in validation features. For an example, see https://stackoverflow.com/a/4140988/7432
You need to use isdigit on strings.
val = '23'
val.isdigit() # True
val = '4'
val.isdigit() # True
val = 'abc'
val.isdigit() # False
If you're not sure what the type of the input is, cast it first to a string before calling isdigit().
If you want only one-digit numbers, you'll have to check if int(val) < 10
isdigit is a string method. Are you expecting a string, an int, or a float?
You can add some typechecking code like this, so that your program validates regardless of whether the value is a numerical type or a string type.
def val(value):
if type(value) in (int, float):
# this is definitely a numerical value
elif type(value) in (str, unicode, bytes):
# this is definitely a string