So I'm just learning Python now, and I wrote this code to practice:
import time
from decimal import Decimal
name = input("\nPlease enter your name: ")
def bmi(weight, height):
bmi = weight/(height**2)
if bmi > 29.9:
report = "obese"
elif bmi <= 29.9 and bmi > 24.9:
report = "overweight"
elif bmi <= 24.9 and bmi > 18.5:
report = "normal"
elif bmi <= 18.5:
report = "underweight"
else:
report = "to be lying"
return (bmi, report)
while True:
weight = Decimal(input("\nEnter your weight (kg): "))
if weight == 0:
print("You can't have a weight of 0. Try again!")
continue
if weight < 0:
print("A negative weight? Really?")
continue
height = Decimal(input("Enter your height (cm): "))
height = height/100
bmi, report = bmi(weight, height)
bmi = round(bmi, 1)
time.sleep(1)
print("\n" + name.title() + ", according to your BMI (" + str(bmi) +
"), you are considered " + report + ".")
qprompt = input("\nDo you wish to quit? (y/n): ")
if qprompt == 'y':
break
else:
continue
This code seems to return an error after the while loop starts again and I input a weight and height. It works fine the first time, but after I tell it to keep running, and then input the weight and height, it crashes and gives this error:
Traceback (most recent call last):
File "BMI2.py", line 33, in <module>
bmi, report = bmi(weight, height)
TypeError: 'decimal.Decimal' object is not callable
I thought I'd ask here for help because I can't figure out the problem.
Thanks!
You're using the symbol bmi in an ambiguous manner.
When you do bmi, report = bmi(weight, height), you essentially override the usage of this symbol as a reference to a function of the same name.
So in the first iteration it references a function, but in the second iteration it references a (non-callable) variable.
Thus, the advantage on a runtime interpreted language is turned against you.
You are writing
bmi = round(bmi, 1)
which makes bmi a number. On the next iteration of your loop, you write
bmi, report = bmi(weight, height)
using it as a function.
Decide whether bmi is the name of your function of your result, and use it consistently
Related
i am a beginner in python and i've tried to create a BMICalculator program and i am currently facing an issue
first up when you open the program it asks the user for their height and weight input
and i have created a try-exception handling for when a user tries to put a string into their Height/Weight input
But the problem is, when a user enters their Height properly, and then uses a string for their Weight, my ValueError exception does show up, but makes the user enter their Height again which is not user friendly,
So what i want to do but don't know how is:
To ask the user again for their Weight input not Height, as they have already entered that
My Code:
import math
import time
def BMICalculator():
print("BMI Calculator!")
try:
Height = float(input("Enter your Height: "))
Weight = float(input("Enter your Weight: "))
Result = Weight / (Height / 100) ** 2
print("Your BMI is: ", round(Result, 1))
if Result <= 18.5:
print("You are underweight")
elif Result <= 24.9:
print("You are healthy")
elif Result <= 29.9:
print("You are overweight")
elif Result > 29.9:
print("You are obese")
except ValueError:
print("Please enter a valid number")
BMICalculator_NoWelcomingMessage()
def BMICalculator_NoWelcomingMessage():
try:
Height = float(input("Enter your Height: "))
Weight = float(input("Enter your Weight: "))
Result = Weight / (Height / 100) ** 2
print("Your BMI is: ", round(Result, 1))
if Result <= 18.5:
print("You are underweight")
elif Result <= 24.9:
print("You are healthy")
elif Result <= 29.9:
print("You are overweight")
elif Result > 29.9:
print("You are obese")
except ValueError:
print("Please enter a valid number")
BMICalculator_NoWelcomingMessage()
def enter_again():
user = input("Do you want to enter again?: ").lower()
while user not in ['yes', 'y', 'no', 'n']:
print("Please enter a valid input")
user = input("Do you want to enter again?: ").lower()
if user not in ['yes', 'y']:
print("Have a nice day!")
time.sleep(1)
elif user not in ['no','n']:
BMICalculator_NoWelcomingMessage()
enter_again()
BMICalculator()
enter_again()
Well, the reason that happens is because you have a single catch statement for both the inputs, and if either of them throws an error, you restart the entire process.
You can fix this with a minor modification, have the two inputs in separate catch blocks, and have a while true loop to keep asking for a valid input till you get one.
Here's what I said in code:
def BMICalculator():
print("BMI Calculator!")
while True:
try:
Height = float(input("Enter your Height: "))
break
except ValueError:
print("Please enter a valid number")
while True:
try:
Weight = float(input("Enter your Weight: "))
break
except ValueError:
print("Please enter a valid number")
Result = Weight / (Height / 100) ** 2
print("Your BMI is: ", round(Result, 1))
Note: You can probably parse the input in a separate function, and call that function when taking input for weight and height, would make the code cleaner. Something like this perhaps:
def parse_input(InputName):
while True:
try:
value = float(input(f"Enter your {InputName}: "))
break
except ValueError:
print("Please enter a valid number")
return value
def BMICalculator():
print("BMI Calculator!")
Height = parse_input("Height")
Weight = parse_input("Weight")
Result = Weight / (Height / 100) ** 2
print("Your BMI is: ", round(Result, 1))
#input
name = input("Enter your name:")
height = input ("Height:")
weight = input ("Weight:")
print("Weight:" + weight +"kg")
print("height:" + height +"m")
print("My name is " + name +"!")
#operations with decimal numbers
metres = float(height)
height_sqr = pow(metres,2)
kg = float(weight)
BMI = float(kg)/height_sqr
#print BMI results
print("BMI:" +str(BMI) +"Kg/M2")
If you want a more optimized method here it is :
# getting input from the user and assigning it to the user
height = float(input("Enter height in meters: "))
weight = float(input("Enter weight in kg: "))
# the formula for calculating bmi
bmi = weight/(height**2)
# ** is the power of operator i.e height*height in this case
print("Your BMI is: {0} and you are: ".format(bmi), end='')
#conditions
if ( bmi < 16):
print("severely underweight")
elif ( bmi >= 16 and bmi < 18.5):
print("underweight")
elif ( bmi >= 18.5 and bmi < 25):
print("Healthy")
elif ( bmi >= 25 and bmi < 30):
print("overweight")
elif ( bmi >=30):
print("severely overweight")
Here you neither have to take input as a string and then convert it into a float nor you have to use a function to calculate power.
It also shows the range in which your BMI lies.
Well, the efficiency of the code will be the same.
I just started picking up python and I want to know how to do what I said in the title. The only background in programming I have is a semester long C++ class that I had in high school that I got a C in and forgot almost everything from. Here's my code:
while True:
try:
height_m = float(input("Enter your height in meters: "))
except ValueError:
print ("Please enter a number without any other characters.")
continue
else:break
while True:
try:
weight_kg = float(input("Enter your weight in kilograms: "))
except ValueError:
print ("Please enter a number without any other characters.")
continue
else:break
bmi = weight_kg / (height_m ** 2)
print ("Your bmi is",(bmi),".")
if bmi < 18.5:
print ("You are underweight.")
elif 18.5 <= bmi <=24.9:
print ("You are of normal weight.")
elif 25 <= bmi <= 29.9:
print ("You are overweight.")
else:
print ("You are obese.")
As you can see, it's just a basic BMI calculator. However, what I wanted to do was make it so that if someone were to input "1.8 m", "1.8 meters" or "1.8 ms" and the equivalent for kilograms, the program would remove the extra input and process it as if they hadn't added that. Also, any extra tips you have for me would be great. Thanks!
Replace the third line with this:
height_m = float(''.join([e for e in input("Enter your height in meters: ") if not e.isalpha()]))
It works by removing all alphabets before converting to float.
In general, this works
Height_List = []
Height = input("What is your height")
for i in Height:
if i in "1234567890.":
Height_List.append(i)
Actual_Height = float("".join(Height_List))
So I am writing a simple program that calculates your BMI. I am running into an issue when it is time to calculate the BMI by taking the returned values of weight and height (it acts as if there is no value being returned). This code use to work when I had all modules in one function, since I have divided all functions into separate modules I have run into this issue.
> Error:
> Traceback (most recent call last):
> File "C:/OneDrive/Documents/3.py", line 43, in <module>
> bmi = calcBMI(weight, height)
> File "C:/OneDrive/Documents/3.py", line 17, in calcBMI
> bmi = float(weight * 703 / (height * height))
> TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
Here's my code:
##########
# Functions
##########
def getweight():
weight = float(input('Enter your weight in LBs: '))
if weight <= 0 or weight > 1000:
print('Weight cannot be less than 0 or greater than 700')
return weight
def getheight():
height = float(input('Enter your height in inches: '))
if height <= 0:
print('Height cannot be less than 0')
return height
def calcBMI(weight, height):
bmi = float(weight * 703 / (height * height))
return bmi
def printData(name, bmi):
print(name)
print('Your BMI is %.2f' % bmi)
if bmi >= 18.5 and bmi <= 24.9:
print('Your BMI is normal')
elif bmi <= 18.5:
print('Your BMI is underweight')
elif bmi >= 25 and bmi <= 29.9:
print('Your BMI is overweight')
elif bmi >= 30:
print('**Your BMI is obese**')
#####################
# Beginning of program
#####################
print("Welcome to the Body Mass Index Calculator")
name = input('Enter your name or 0 to quit: ')
# beginning of loop
while name != "0":
height = getheight()
weight = getweight()
bmi = calcBMI(weight, height)
printData(name, weight, height, bmi)
name = input('Enter another name or 0 to quit: ')
print("Exiting program...")
For a start, you are only returning height if it is less than 0. You would want to remove the return statement from within the if block.
You probably also want to create some logic to deal with an incorrect height being entered, such as raising an exception, or returning the user to the prompt.
def getweight():
weight = float(input('Enter your weight in LBs: '))
if weight <= 0 or weight > 1000:
print('Weight cannot be less than 0 or greater than 700')
#Some code here to deal with a weight less than 0
return weight
def getheight():
height = float(input('Enter your height in inches: '))
if height <= 0:
print('Height cannot be less than 0')
#Some code here to deal with a height less than 0
return height
One way of dealing with incorrect weights would be:
def getweight():
while True:
weight = float(input('Enter your weight in LBs: '))
if weight <= 0 or weight > 1000:
print('Weight cannot be less than 0 or greater than 700')
else:
return weight
You may want to limit this to a certain number of iterations - up to you.
Neither getheight nor getweight necessarily returns a number (i.e. when the if fails); in such cases, it returns None.
I am new to python and and currently learning to use functions properly.
I have been tasked with making a bmi calculator using python for my homework. This bmi calculator must give the option of whether to use metric or imperial units. based on this option it will then ask for your weight and height in the respectable unit type. This is where the problem stats - no matter what i input it still uses metric units and just seems to ignore my if/elif/else statments. so this is the first problem and i cant understand where i have gone wrong here.
after that problem is solved, the bmi that it calculates needs to be put into a category and then the program should tell you which category your bmi fits into, this part doesn't even work for the metric bmi it just says:
"""this is the error i keep getting, the actual code for the program is below"""
traceback (most recent call last):
File "C:/Python33/bmi calculator 2 2 2 2.py", line 54, in <module>
catagory(bmi)
File "C:/Python33/bmi calculator 2 2 2 2.py", line 45, in catagory
if bmi <18.5:
TypeError: unorderable types: tuple() < float()
"""this is a bmi calculator that works in both imperial and metric units
and can tell your bmi category"""
bmi = ()
metric = ("metric")
Metric = ("Metric")
imperial = ("imperial")
Imperial = ("Imperial")
MetricBMI = ()
ImperialBMI = ()
answer = input (" Do you want to work out you BMI using Metric or Imperial units?")
def BMI():
metric = ("metric")
Metric = ("Metric")
imperial = ("imperial")
Imperial = ("Imperial")
if answer.lower() == metric:
print("You have chose to calculate your bmi in metric units")
Weight_kg = float(input("What is your weight in kilograms (kg)"))
Height_m = float(input("What is your height in meters (m)?"))
bmi = Weight_kg/Height_m/Height_m
print("Your BMI is " + str(bmi))
elif answer.lower() == imperial:
print ("You have chosen to calculate your bmi in imperial units")
Weight_lbs = float(input("What is your weight in pounds (lbs)?"))
Height_inches = float(input("What is your height in inches??"))
bmi = Weight_lbs*703/Height_inches/Height_inches
print ("Your BMI is " + str(bmi))
else:
print ("please restart and enter either 'imperial' or 'metric'")
BMI()
def catagory(bmi):
if bmi <18.5:
return ("You are underweight")
elif bmi >=18.5 and bmi <25:
return ("You are normal weight")
elif bmi >= 25 and bmi <30:
return ("you are overweight")
elif bmi >=30:
return ("you are obese")
catagory(bmi)
Is this what you wish to do?
def catagory(BMI):
if BMI < 18.5:
print "You are underweight"
elif BMI >= 18.5 and BMI <25:
print "You are normal weight"
elif BMI >= 25 and BMI <30:
print "you are overweight"
elif BMI >= 30:
print "you are obese"
def BMI():
choice = raw_input("SI or Imperial? ")
weight = int(raw_input("weight: "))
height = int(raw_input("height: "))
if choice == "SI":
BMI = weight / (height * height)
if choice == "Imperial":
BMI = (weight * 703) / (height * height)
return BMI
BMI = BMI()
catagory(BMI)
Your BMI function dosn't return the value that was calculated for the BMI. To change this you can either let the function return the value of BMI to the main script, as shown above with "return BMI". Or you can declare BMI a global variable in your BMI function
Since your BMI function is modifying the global variable bmi, it needs to declare it:
def BMI():
global bmi
...
Without the global declaration, Python creates a local bmi variable, which is forgotten when the function finishes. The error you see is the result of the attempt to use the unchanged initial value of the global bmi variable. You would do well to remove this initialization altogether or get rid of the global variable altogether.