After reflecting and reading other answers, I found that Adam Smith is right: we should get rid of the class. For this problem I think that it's better to structure the program as a group of functions. This is my new answer.
Variable names should be lowercase, so your variable
BMI should be renamed
According to Wikipedia, "In software design, modularity refers to a logical partitioning of the "software design" that allows complex software to be manageable for the purpose of implementation and maintenance. The logic of partitioning may be based on related functions, implementation considerations, data links, or other criteria." So you should divide your code into smaller units, for this purpose we will divide your code into a group of functions.
This is better, because it's a bad practice, IMHO, to write all your code as a single whole without dividing it into units. This makes your code reusable, readable, and maintainable.
It's a good practice, IMHO, to document your code, this makes it more readable and easier to use. For this purpose we will use docstrings to document the functions that we'll define. Docstings are indented and contained into triple quotes, they describe what the function does, its arguments, the type of its arguments, its return value and the type of the return value (when used with functions). Docstrings are the right way to document functions, not comments, because if you need help about using the function, you can use
help(name here) to display the docstring and get help, which you can't do with comments.
Dividing the Code into Functions
To achieve modularity, we'll divide the code into functions. We'll define:
a boolen-valued function (a function that returns only
False) that asks whether the user wants to start. We will rename
upper method, we'll make the input uppercase, so we can compare it to 'Y' and 'N' easily if the user entered 'y' or 'n' instead.
a function that handles both weight and height.
a function that takes calculates the BMI and returns it.
a function that returns the weight status.
a function called
main that contains all the code that will be executed. We'll use it as the body of
if __name__ == '__main__' by calling it.
Instead of making our new functions print the output, we'll make them return it. You can read about return values here (this is a link to chapter in Think Python 2e, I recommend that you read the whole book). Just printing the output gets the job done but makes functions less reusable. Suppose that you want to store the BMIs associated with users in a textfile, what will you do? Sure you can make other functions to get this done, but if you make your functions return the result you can reuse many cases.
Code after Refactoring
def body_mass_index(weight, height):
"""Returns the BMI based on weight and height.
weight: float or int
height: float or int
Returns: float or int
return round(weight / height ** 2 , 2)
"""Returns the weight category of the user based on their BMI.
if bmi < 18.5:
elif 18.5 <= bmi <= 24.99:
return 'healthy weight'
elif 25.0 <= bmi <= 29.99:
elif bmi > 30:
"""Asks whether the user wants to start.
answer = input("Y to start N to exit: ").upper()
if answer == 'Y':
elif answer == 'N':
print('Please try again.\n')
"""Asks for the user's weight and height.
Rerurns: tuple of 2 floats or integers
weight = float(input('Enter your weight in kilograms: '))
height = float(input('Enter your height in meters: '))
if 0 < weight and 0 < height:
return weight, height
print('Invalid input for weight or height')
weight, height = get_user_data()
bmi = body_mass_index(weight, height)
category = weight_category(bmi)
print('Your BMI is: ', bmi)
print('Your are ', category, '.')
if __name__ == '__main__':
get_user_data is adopted from Lukasz Salitra's function
_get_user_info in his answer to the OP's previous question. You can find the question here.
I'm no expert on BMI, so I've no idea if the program does what it's supposed to do properly. I focused on making the code more reusable, readable, and well-structured, according to what I know as a beginner.