python-3.xvalueerrorundefined-variable

Variable undefined error when it is clearly defined?


def standardCalBurn(weight, height, age):
    calories_needed = 655 + (4.3 * weight) + (4.7 * height) - (4.7 * age)
    print(f"{calories_needed:.1f} calories are needed per day to sustain weight of {weight}")

def burnedRunning(weight):
    calories_burned_per_minute = weight * 0.095
    return calories_burned_per_minute

def burnedWalking(weight):
    calories_burned_per_minute = weight * 0.054
    return calories_burned_per_minute

def burnedJogging(weight):
    calories_burned_per_minute = weight * 0.0775
    return calories_burned_per_minute

weight = float(input("Please enter your weight: "))
height = float(input("Please enter your height (in inches): "))
age = float(input("Please enter your age: "))

standardCalBurn(weight, height, age)

calories_to_burn = float(input("How many calories do you wish to burn while exercising? "))

activity = ""

while activity in ["WALK", "RUN", "JOG"]:
    if activity == "WALK":
        calories_burned_per_minute = burnedWalking(weight)
    if activity == "RUN":
        calories_burned_per_minute = burnedRunning(weight)
    if activity == "JOG":
        calories_burned_per_minute = burnedJogging(weight)
    if activity not in ["WALK", "JOG", "RUN"]:
        activity = input("Invalid input. Will you WALK, RUN, or JOG? ").upper()

minutes_to_burn = calories_to_burn / calories_burned_per_minute

print(f"You will burn {calories_burned_per_minute:.2f} calories per minute")
print(f"You will need to {activity} for {minutes_to_burn:.2f} minutes")

Whenever I try to run my code, it is saying calories_burned_per_minute is undefined when I clearly previously defined. Any help is appreciated. Thank you.

Traceback (most recent call last): File "", line 37, in NameError: name 'calories_burned_per_minute' is not defined


Solution

  • NameError is raised is not a bug, it is the correct behavior, because calories_burned_per_minute is indeed undefined.

    Why? Because your loop didn't run. '' isn't a member of ["WALK", "RUN", "JOG"]. So activity in ["WALK", "RUN", "JOG"] is false.

    Your while loop didn't run, because while loop only runs as long as condition is satisfied and stops when the condition is no longer met. Here your condition is never met.

    Try this:

    while False:
        print(True)
    

    What happens? Exactly Nothing.

    Change while activity in ["WALK", "RUN", "JOG"] to while activity not in ["WALK", "RUN", "JOG"]

    Then your logic of getting the input is completely wrong.

    You should do this:

    while activity not in ["WALK", "RUN", "JOG"]:
        activity = input("Invalid input. Will you WALK, RUN, or JOG? ").upper()
    

    Then this:

    functions = {'WALK': burnedWalking, 'RUN': burnedRunning, 'JOG': burnedJogging}
    calories_burned_per_minute  = functions[activity](weight)
    

    Using match case:

    match activity:
        case 'WALK':
            func = burnedWalking
        case 'RUN':
            func = burnedRunning
        case 'JOG':
            func = burnedJogging
    calories_burned_per_minute  = func(weight)
    

    And you have three functions with only one value that is different, this is bad, just use one function and pass the second value as argument. Your function names also doesn't follow the Python naming convention, and your variable names are also overly long, and you don't inline variables that are immediately returned, and you print inside functions, and you use input function rather than taking arguments, and you didn't do type hinting...

    I have refactored your code and removed all the cruft:

    from enum import Enum
    
    
    class Activity(Enum):
        Run = 0.095
        Jog = 0.0775
        Walk = 0.054
    
    
    def standard_burn(weight: int | float, height: int | float, age: int | float) -> float:
        return 655 + (4.3 * weight) + (4.7 * height) - (4.7 * age)
    
    
    def burn(weight: int | float, act: Activity):
        return weight * act.value
    
    
    def calc_calories(
        weight: int | float,
        height: int | float,
        age: int | float,
        target: int | float,
        act: Activity,
    ) -> None:
        burn_rate = burn(weight, act)
        duration = target / burn_rate
        print(f"You will burn {burn_rate:.2f} calories per minute")
        print(f"You will need to {act} for {duration:.2f} minutes")
        print(
            f"{standard_burn(weight, height, age):.1f} calories are needed per day to sustain weight of {weight}"
        )
    

    Use like this:

    In [12]: calc_calories(1, 1, 1, 1, Activity.Walk)
    You will burn 0.05 calories per minute
    You will need to Activity.Walk for 18.52 minutes
    659.3 calories are needed per day to sustain weight of 1