I\'m taking a tutorial in udemy to teach myself Python and it is making me love Javascript every day more. Anyhow, I can\'t seem to figure out how to work this indentation right
didn't I define them already in their functions
Yes, and that's the problem. They are locally scoped to those functions. You need assignment... weight = getWeight()
, for example
No need to go overboard with the function definitions, though
def calcBMI(weight, height):
bmi = (weight * 703) / (height * height)
return bmi
def showBMI(bmi):
print("BMI Index:", "{:.2f}".format(bmi))
student_name = input("Enter the student's name or 0 to exit:")
while student_name != "0":
weight = float(input("Enter " + student_name + "'s weight in pounds: "))
height = float(input("Enter " + student_name + "'s height in pounds: "))
bmi = calcBMI(weight, height)
# etc...
showBMI(bmi)
student_name = input("Enter next student's name or 0 to exit:")
print("\n\nExiting Program!")
You are getting the weight, height and bmi, but you are just throwing away the result. These variables are local to the inner function scopes, so they are invisible for your outer function.
Doing:
weigth = getWeight()
height = getHeight()
bmi = calcBMI(weight, height)
Fixes the problem.
Also, a note on squiggly brackets and semicolons; In Python an indented block with the same indentation level is equivalent to a pair of squiggly brackets in other languages. While line breaks translates to semicolons.
a = 1
b = 2
if True:
c = 3
<=>
{
a = 1;
b = 2;
if (True) {
c = 3;
}
}
However, there are a few (convenient) exceptions. Like when a line is ended without a closing parenthesis, no "virtual semicolon" is inserted. Also, an inner Python scope does not hide its local variables to an outer scope unless the scoping is due to a function.
You are accessing a variable outside the scope. For instance the weight variable is defined in the scope of the getWeight()
function but you are trying to access it from the BMICalculator()
scope.
You should properly scope your variables, you have two options. Define the functions as closures or just use the return value. Below I how the second option.
def BMICalculator():
student_name = input("Enter the student's name or 0 to exit:")
while student_name != "0":
def getWeight():
weight = float(input("Enter " + student_name + "'s weight in pounds: "))
return weight
def getHeight():
height = float(input("Enter " + student_name + "'s height in pounds: "))
return height
def calcBMI(weight, height):
bmi = (weight * 703) / (height * height)
return bmi
# here you have to define the weight, height and bmi
# variables in this scope.
weight = getWeight()
height = getHeight()
bmi = calcBMI(weight, height)
print("\n" + student_name + "'s BMI profile:")
print("---------------")
print("Height:", height, "\nWeight:", weight)
def showBMI(bmi):
print("BMI Index:", "{:.2f}".format(bmi))
showBMI(bmi)
student_name = input("Enter next student's name or 0 to exit:")
print("\n\nExiting Program!")
To clarify, you should try moving the functions outside the loop (putting them at the same level as BMICalculator()
. This will probably clarify the scoping problem to you.
def getWeight():
weight = float(input("Enter " + student_name +
"'s weight in pounds: "))
return weight
def getHeight():
height = float(input("Enter " + student_name +
"'s height in pounds: "))
return height
def calcBMI(weight, height):
bmi = (weight * 703) / (height * height)
return bmi
def BMICalculator():
student_name = input("Enter the student's name or 0 to exit:")
while student_name != "0":
# Now it is more evident that the weight, height and bmi
# variables in the above functions are only defined in the
# scope of the respective function, the BMICalculator scope
# is different and the names "weight", "height" and "bmi" are
# not bound to anything, hence the NameError.
weight = getWeight()
height = getHeight()
bmi = calcBMI(weight, height)
print("\n" + student_name + "'s BMI profile:")
print("---------------")
print("Height:", height, "\nWeight:", weight)
def showBMI(bmi):
print("BMI Index:", "{:.2f}".format(bmi))
showBMI(bmi)
student_name = input("Enter next student's name or 0 to exit:")
Scoping in python has some simple yet important rules, I suggest you have a look at this answer for a quick overview of the scope resolution.
As an aside, the problem you are having is not python-related, any decent (or at least those I know) programming language (even javascript) would treat those variables as out of scope.
Hope this helps.