0

I am making a BMI calculator with plotly Dash. I'm trying to code it where the user choses the unit of the input for weight and height, however its throwing an error on line 38:

UnboundLocalError: local variable 'bmi' referenced before assignment

from dash import Dash, dcc, html, Input, Output

app = Dash(__name__)

app.layout = html.Div([
    html.H1("BMI Calculator"),
    html.Div([
        html.H2('Enter your weight'),
        dcc.Input(id = 'weight', value = 160, type = 'number'),
        dcc.RadioItems(options = [{'label': 'pounds', 'value': 'lbs'}, {'label': 'kilograms', 'value': 'kgs'}], 
                       value = 'lbs',
                       id = 'weight_unit'),
        html.H2('Enter your height'),
        dcc.Input(id = 'height', value = 5.83333333, type = 'number'),
        dcc.RadioItems(options = [{'label': 'feet', 'value': 'ft'},{'label': 'meters', 'value': 'm'}], 
                       value = 'ft', 
                       id = 'height_unit'),      
    ]),
    html.Br(),
    html.H1("Your estimated body mass index is:"),
    html.H1(id = 'bmi'),

])

@app.callback(
    Output(component_id = 'bmi', component_property = 'children'),
    Input(component_id  = 'weight', component_property = 'value'),
    Input(component_id  = 'weight_unit', component_property = 'value'),
    Input(component_id  = 'height', component_property = 'value'),
    Input(component_id  = 'height_unit', component_property = 'value'),
   )
    
def update_output_div(weight, weight_unit, height, height_unit):
    if weight_unit == 'lbs' and height_unit == 'ft':
        bmi = 703 * (weight/(height * 12)**2)
    if weight_unit == 'kgs' and height_unit == 'm':
        bmi = (weight)/((height)**2)
    return bmi 

if __name__ == '__main__':
    app.run_server(debug=True)

rerecodes
  • 33
  • 5
  • Welcome to Stack Overflow. In your own words, where the code says `return bmi`, why should `bmi` mean anything at all? For example, what do you expect would happen, if `weight_unit` isn't equal to either `'lbs'` or `'ft'`? **Did you try to check** what `weight_unit` and `height_unit` are equal to, when this code runs? – Karl Knechtel Mar 12 '23 at 05:35

1 Answers1

1

Using return on a variable that was assigned within an if block means that the variable will only be assigned if that condition is met. Otherwise, when the code doesn't run, the variable bmi does not get defined, and cannot be returned.

To resolve the problem, one way is to assign a value before the if statement.

def update_output_div(weight, weight_unit, height, height_unit):
    bmi = None
    if weight_unit == 'lbs' and height_unit == 'ft':
        bmi = 703 * (weight/(height * 12)**2)
    if weight_unit == 'kgs' and height_unit == 'm':
        bmi = (weight)/((height)**2)
    return bmi 
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
ARK1375
  • 790
  • 3
  • 19
  • "ambiguity" isn't a technical term, by the way - it's perfectly ordinary English, so it doesn't need to be introduced with language like "something called". – Karl Knechtel Mar 12 '23 at 05:35
  • (On a closer reading, there were many smaller problems with your use of terminology. In particular, Python **does not have** declarations. I have edited to fix the issues, as well as generally trying to write more clearly. However, this question is a duplicate anyway.) – Karl Knechtel Mar 12 '23 at 05:39
  • @KarlKnechtel Thank you for editing my answer. But, Really? It doesn't have declarations? I mean, isn't it that when you assign a value to a variable you are basically declaring it in the variable table? – ARK1375 Mar 12 '23 at 05:43
  • 1
    Of course it doesn't. The first time a name is assigned is just like any other time (except for the part where there wasn't anything already assigned). When Python compiles the code, it infers what names are used in the code by seeing what tokens match the pattern for identifiers, and it doesn't care whether any kind of assignment to those names occurs, or in what order/context the names appear. Python's names also don't have any type inherently associated with them; the newly introduced "annotations" feature is just what it sounds like - a mere suggestion, for use by third-party tools. – Karl Knechtel Mar 12 '23 at 05:46