BMI calculator in python using if statements
I am a beginner in the python language. I wrote a BMI calculator and I am wondering if there are any improvements I could make to the code. This is the code below:
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
print('Your BMI = ' + str(bodyMassIndex) + ' You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
print('Your BMI = ' + str(bodyMassIndex) + ' You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
print('Your BMI = ' + str(bodyMassIndex) + ' You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
print('Your BMI = ' + str(bodyMassIndex) + ' You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely obese.')
elif bodyMassIndex > 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely obese.')
input('Please press Enter to exit')
python calculator
add a comment |
I am a beginner in the python language. I wrote a BMI calculator and I am wondering if there are any improvements I could make to the code. This is the code below:
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
print('Your BMI = ' + str(bodyMassIndex) + ' You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
print('Your BMI = ' + str(bodyMassIndex) + ' You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
print('Your BMI = ' + str(bodyMassIndex) + ' You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
print('Your BMI = ' + str(bodyMassIndex) + ' You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely obese.')
elif bodyMassIndex > 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely obese.')
input('Please press Enter to exit')
python calculator
1
FYI, some 2017 research indicates that waist-to-height ratio is a better obesity index when predicting 'metabolic syndrome' for individuals. You could extend your code to return that information as well, or at least note in the output that the code judges an 'obese' condition based only on BMI, out of multiple possible obesity indices.
– user117529
Dec 31 '18 at 23:50
add a comment |
I am a beginner in the python language. I wrote a BMI calculator and I am wondering if there are any improvements I could make to the code. This is the code below:
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
print('Your BMI = ' + str(bodyMassIndex) + ' You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
print('Your BMI = ' + str(bodyMassIndex) + ' You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
print('Your BMI = ' + str(bodyMassIndex) + ' You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
print('Your BMI = ' + str(bodyMassIndex) + ' You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely obese.')
elif bodyMassIndex > 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely obese.')
input('Please press Enter to exit')
python calculator
I am a beginner in the python language. I wrote a BMI calculator and I am wondering if there are any improvements I could make to the code. This is the code below:
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
print('Your BMI = ' + str(bodyMassIndex) + ' You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
print('Your BMI = ' + str(bodyMassIndex) + ' You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
print('Your BMI = ' + str(bodyMassIndex) + ' You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
print('Your BMI = ' + str(bodyMassIndex) + ' You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are severely obese.')
elif bodyMassIndex > 40:
print('Your BMI = ' + str(bodyMassIndex) + ' You are very severely obese.')
input('Please press Enter to exit')
python calculator
python calculator
edited Dec 30 '18 at 15:03
Reinderien
4,140822
4,140822
asked Dec 30 '18 at 8:01
Somtobechukwu PaulSomtobechukwu Paul
785
785
1
FYI, some 2017 research indicates that waist-to-height ratio is a better obesity index when predicting 'metabolic syndrome' for individuals. You could extend your code to return that information as well, or at least note in the output that the code judges an 'obese' condition based only on BMI, out of multiple possible obesity indices.
– user117529
Dec 31 '18 at 23:50
add a comment |
1
FYI, some 2017 research indicates that waist-to-height ratio is a better obesity index when predicting 'metabolic syndrome' for individuals. You could extend your code to return that information as well, or at least note in the output that the code judges an 'obese' condition based only on BMI, out of multiple possible obesity indices.
– user117529
Dec 31 '18 at 23:50
1
1
FYI, some 2017 research indicates that waist-to-height ratio is a better obesity index when predicting 'metabolic syndrome' for individuals. You could extend your code to return that information as well, or at least note in the output that the code judges an 'obese' condition based only on BMI, out of multiple possible obesity indices.
– user117529
Dec 31 '18 at 23:50
FYI, some 2017 research indicates that waist-to-height ratio is a better obesity index when predicting 'metabolic syndrome' for individuals. You could extend your code to return that information as well, or at least note in the output that the code judges an 'obese' condition based only on BMI, out of multiple possible obesity indices.
– user117529
Dec 31 '18 at 23:50
add a comment |
3 Answers
3
active
oldest
votes
This kind of programming exercice, despite its apparent simplicity, is a good opportunity to learn various things.
Style
Python has a Code Style guide called PEP 8. If you begin with Python, I highly recommend reading it every now and then and trying to apply it.
In your case, a few things could be improved regarding style:
- blank lines between the different branches of
if
are more an inconvenience from my point of view - variables should follow the
snake_case
naming convention (instead ofcamelCase
)
Builtin input
As you've noticed for the end of the function, the input
builtin takes an optional prompt
parameter. This could be used at the beginning of the function as well.
Duplicated code
A lot of code looks like the same line with minimal variations. Having duplicated code makes the code more tedious to read and harder to maintain (if you need to change something, you'll need to change it in many places). One of the principles of software programming is Don't Repeat Yourself (also written DRY).
In your case, we could store the body category in a variable and only print the ouput from a single place:
Chained comparison
This is very specific to Python but instead of body_mass_index > 30 and body_mass_index <= 35
, we can write: 30 < body_mass_index <= 35
using chained comparisons.
Magic numbers
Magic Numbers are usually frowned upon. In our case, one needs a bit of thinking to understand where the 12
and 0.025
come from. A better way to handle this is to store them in a variable with a meaningful name.
I am not quite sure about the best naming convention for names related to conversion constant. I've followed the names suggested by Solomon Ucko in the comments.
At this stage, we have the following code:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
body_mass_index = weight_in_kilo / (height_in_meter ** 2)
if body_mass_index < 15:
category = 'very severely underweight'
elif 15 <= body_mass_index <= 16 :
category = 'severely underweight'
elif 16 < body_mass_index <= 18.5:
category = 'underweight'
elif 18.5 < body_mass_index <= 25:
category = 'Normal(healthy weight)'
elif 25 < body_mass_index <= 30:
category = 'overweight'
elif 30 < body_mass_index <= 35:
category = 'moderately obese'
elif 35 < body_mass_index <= 40:
category = 'severely obese'
elif body_mass_index > 40:
category = 'very severely obese'
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
Which can still be improved.
Mutually exclusive conditions
Because of the way we check body_mass_index
, if it is under 15, we get into the first case so there is no need to check elif 15 <= body_mass_index
in the else
part. This is guaranteed to be always true. Similarly, half the checks have no effect.
Code organisation
To make the code easier to understand (and easier to reuse, to test, etc), it is a good habit to split in into smaller reusable chunks. In our case, defining functions could be a nice touch.
Disclaimer: Next paragraph can be a bit overwhelming for a beginner, do not worry if you do not fully get it. It highlights how to solve problems you may not be interested in yet but it is a good chance to do things properly.
Also, if we want to be able to actually reuse your functions, we want to be able to import
the file. Currently, if we do so, we get stuck into the parts asking for user inputs. Thus, the usual strategy is the following: split your code into 2 parts:
code defining functions/constants/classes/etc but without any side-effect or user interactions
code actually doing things (input/output, etc) behind an
if __name__ == "__main__":
guard. As pointed out by Solomon Ucko, it's generally a good idea to have this performed via amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
At this stage, we have:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
def convert_feet_to_meter(height_in_feet):
return height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
def get_body_mass_index(height_in_meter, weight_in_kilo):
return weight_in_kilo / (height_in_meter ** 2)
def get_category(body_mass_index):
if body_mass_index < 15:
return 'very severely underweight'
elif body_mass_index <= 16 :
return 'severely underweight'
elif body_mass_index <= 18.5:
return 'underweight'
elif body_mass_index <= 25:
return 'Normal(healthy weight)'
elif body_mass_index <= 30:
return 'overweight'
elif body_mass_index <= 35:
return 'moderately obese'
elif body_mass_index <= 40:
return 'severely obese'
else:
return 'very severely obese'
def main():
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = convert_feet_to_meter(height_in_feet)
body_mass_index = get_body_mass_index(height_in_meter, weight_in_kilo)
category = get_category(body_mass_index)
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
if __name__ == "__main__":
main()
Going further, a few more details could be improved.
String formatting
Python offers many tools to format strings so that you do not need to use string concatenations. You can refer to PyFormat.info for documentations and examples.
You could write:
print('Your BMI = %f You are %s.' % (body_mass_index, category))
Or the newer technique:
print('Your BMI = {} You are {}.'.format(body_mass_index, category))
Also, in Python 3.6, yet another soution was added: F-strings.
Data over code
This may be a bit overkill here but sometimes a lot of code can be replaced by a small amount of code working on a properly filled data structure. In our case, the get_category
function does the same thing for all categories: check the if we are under a given limit and if so, return the category name.
Disclaimer: Next part works under the assumption that body_mass_index < 15
should actually use <=
like the other cases.
# List of pairs (higher-limit, name) sorted
CATEGORIES = [
(15, 'very severely underweight'),
(16, 'severely underweight'),
(18.5, 'underweight'),
(25, 'Normal(healthy weight)'),
(30, 'overweight'),
(35, 'moderately obese'),
(40, 'severely obese'),
]
def get_category(body_mass_index):
for limit, name in CATEGORIES:
if body_mass_index <= limit:
return name
return 'very severely obese'
1
I haven't written python for a few years, but couldn't you only use if and return with a response function as soon as a condition is met?
– Džuris
Dec 30 '18 at 15:09
@Džuris I am not quite sure what you mean. Could you write somewhere ( pastebin.com ?) what you have in mind ?
– Josay
Dec 30 '18 at 15:13
sorry, I somehow misread a sample and was suggesting an idea similar to what's already there. Now that I read it properly on a computer, my question boils down to: Why do you needelif
(instead ofif
) andelse
in the second sample? Isn't it that a later condition is only reached if none of the previous are met and justif
(or nothing for the last case) would be enough?
– Džuris
Dec 30 '18 at 17:43
@Džuris Indeed, it would be the same. I kept the originalelif
because it didn't bother me. Then it is just a matter of personal preference. I have no strong opinion on this.
– Josay
Dec 30 '18 at 18:00
1
It's generally a good idea to have amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
– Solomon Ucko
Dec 31 '18 at 3:26
|
show 4 more comments
One big refactoring that you could do is to remove all the if/else causes.
For example:
def compute_bmi(weight_in_kilo, height_in_feet):
STUPID_CONVERSION_CONSTANT = 12 * 0.025
return weight_in_kilo / ((height_in_feet * STUPID_CONVERSION_CONSTANT) ** 2)
def find_key_from_bmi(bmi):
keys = list(bmi_info.keys())
mins = [k if k <= bmi else 0 for k in keys]
return keys[mins.index(min(mins))]
def print_message(bmi):
print(f"Your BMI is {bmi} which means you are {bmi_info[find_key_from_bmi(bmi)]}.")
bmi_info = {
15: 'very severely underweight',
16: 'severely underweight',
18.5: 'underweight',
25: 'normal (healthy weight)',
30: 'overweight',
35: 'moderately obese',
40: 'severely obese',
}
print_message(compute_bmi(float(input("Enter you weight in kilo:")), float(input("Enter your height in feet:"))))
This scales to an arbitrary large number of categories (possibly automatically generated) without the need to write extra code.
Why do youimport numpy
? Also, it's probably best to define the constant outside the loop and with a descriptive name such asMETERS_PER_FOOT
.
– Solomon Ucko
Jan 1 at 2:33
Numpy was a leftover for no valid reason.
– Cedric H.
Jan 1 at 11:33
add a comment |
Well, you could refactor the print part and extract it to a function like this:
def printBMIMessage(bodyMassIndex, message):
print('Your BMI = ' + str(bodyMassIndex) + ' ' + message)
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
printBMIMessage(bodyMassIndex, 'You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
printBMIMessage(bodyMassIndex, 'You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
printBMIMessage(bodyMassIndex, 'You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
printBMIMessage(bodyMassIndex, 'You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
printBMIMessage(bodyMassIndex, 'You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
printBMIMessage(bodyMassIndex, 'You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
printBMIMessage(bodyMassIndex, 'You are severely obese.')
elif bodyMassIndex > 40:
printBMIMessage(bodyMassIndex, 'You are very severely obese.')
input('Please press Enter to exit')
I don't really like the control flow of theprintBMIMessage
function because it allows to doprintBMIMessage(40, 'You are underweight')
.
– svavil
Dec 30 '18 at 19:59
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210592%2fbmi-calculator-in-python-using-if-statements%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
This kind of programming exercice, despite its apparent simplicity, is a good opportunity to learn various things.
Style
Python has a Code Style guide called PEP 8. If you begin with Python, I highly recommend reading it every now and then and trying to apply it.
In your case, a few things could be improved regarding style:
- blank lines between the different branches of
if
are more an inconvenience from my point of view - variables should follow the
snake_case
naming convention (instead ofcamelCase
)
Builtin input
As you've noticed for the end of the function, the input
builtin takes an optional prompt
parameter. This could be used at the beginning of the function as well.
Duplicated code
A lot of code looks like the same line with minimal variations. Having duplicated code makes the code more tedious to read and harder to maintain (if you need to change something, you'll need to change it in many places). One of the principles of software programming is Don't Repeat Yourself (also written DRY).
In your case, we could store the body category in a variable and only print the ouput from a single place:
Chained comparison
This is very specific to Python but instead of body_mass_index > 30 and body_mass_index <= 35
, we can write: 30 < body_mass_index <= 35
using chained comparisons.
Magic numbers
Magic Numbers are usually frowned upon. In our case, one needs a bit of thinking to understand where the 12
and 0.025
come from. A better way to handle this is to store them in a variable with a meaningful name.
I am not quite sure about the best naming convention for names related to conversion constant. I've followed the names suggested by Solomon Ucko in the comments.
At this stage, we have the following code:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
body_mass_index = weight_in_kilo / (height_in_meter ** 2)
if body_mass_index < 15:
category = 'very severely underweight'
elif 15 <= body_mass_index <= 16 :
category = 'severely underweight'
elif 16 < body_mass_index <= 18.5:
category = 'underweight'
elif 18.5 < body_mass_index <= 25:
category = 'Normal(healthy weight)'
elif 25 < body_mass_index <= 30:
category = 'overweight'
elif 30 < body_mass_index <= 35:
category = 'moderately obese'
elif 35 < body_mass_index <= 40:
category = 'severely obese'
elif body_mass_index > 40:
category = 'very severely obese'
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
Which can still be improved.
Mutually exclusive conditions
Because of the way we check body_mass_index
, if it is under 15, we get into the first case so there is no need to check elif 15 <= body_mass_index
in the else
part. This is guaranteed to be always true. Similarly, half the checks have no effect.
Code organisation
To make the code easier to understand (and easier to reuse, to test, etc), it is a good habit to split in into smaller reusable chunks. In our case, defining functions could be a nice touch.
Disclaimer: Next paragraph can be a bit overwhelming for a beginner, do not worry if you do not fully get it. It highlights how to solve problems you may not be interested in yet but it is a good chance to do things properly.
Also, if we want to be able to actually reuse your functions, we want to be able to import
the file. Currently, if we do so, we get stuck into the parts asking for user inputs. Thus, the usual strategy is the following: split your code into 2 parts:
code defining functions/constants/classes/etc but without any side-effect or user interactions
code actually doing things (input/output, etc) behind an
if __name__ == "__main__":
guard. As pointed out by Solomon Ucko, it's generally a good idea to have this performed via amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
At this stage, we have:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
def convert_feet_to_meter(height_in_feet):
return height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
def get_body_mass_index(height_in_meter, weight_in_kilo):
return weight_in_kilo / (height_in_meter ** 2)
def get_category(body_mass_index):
if body_mass_index < 15:
return 'very severely underweight'
elif body_mass_index <= 16 :
return 'severely underweight'
elif body_mass_index <= 18.5:
return 'underweight'
elif body_mass_index <= 25:
return 'Normal(healthy weight)'
elif body_mass_index <= 30:
return 'overweight'
elif body_mass_index <= 35:
return 'moderately obese'
elif body_mass_index <= 40:
return 'severely obese'
else:
return 'very severely obese'
def main():
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = convert_feet_to_meter(height_in_feet)
body_mass_index = get_body_mass_index(height_in_meter, weight_in_kilo)
category = get_category(body_mass_index)
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
if __name__ == "__main__":
main()
Going further, a few more details could be improved.
String formatting
Python offers many tools to format strings so that you do not need to use string concatenations. You can refer to PyFormat.info for documentations and examples.
You could write:
print('Your BMI = %f You are %s.' % (body_mass_index, category))
Or the newer technique:
print('Your BMI = {} You are {}.'.format(body_mass_index, category))
Also, in Python 3.6, yet another soution was added: F-strings.
Data over code
This may be a bit overkill here but sometimes a lot of code can be replaced by a small amount of code working on a properly filled data structure. In our case, the get_category
function does the same thing for all categories: check the if we are under a given limit and if so, return the category name.
Disclaimer: Next part works under the assumption that body_mass_index < 15
should actually use <=
like the other cases.
# List of pairs (higher-limit, name) sorted
CATEGORIES = [
(15, 'very severely underweight'),
(16, 'severely underweight'),
(18.5, 'underweight'),
(25, 'Normal(healthy weight)'),
(30, 'overweight'),
(35, 'moderately obese'),
(40, 'severely obese'),
]
def get_category(body_mass_index):
for limit, name in CATEGORIES:
if body_mass_index <= limit:
return name
return 'very severely obese'
1
I haven't written python for a few years, but couldn't you only use if and return with a response function as soon as a condition is met?
– Džuris
Dec 30 '18 at 15:09
@Džuris I am not quite sure what you mean. Could you write somewhere ( pastebin.com ?) what you have in mind ?
– Josay
Dec 30 '18 at 15:13
sorry, I somehow misread a sample and was suggesting an idea similar to what's already there. Now that I read it properly on a computer, my question boils down to: Why do you needelif
(instead ofif
) andelse
in the second sample? Isn't it that a later condition is only reached if none of the previous are met and justif
(or nothing for the last case) would be enough?
– Džuris
Dec 30 '18 at 17:43
@Džuris Indeed, it would be the same. I kept the originalelif
because it didn't bother me. Then it is just a matter of personal preference. I have no strong opinion on this.
– Josay
Dec 30 '18 at 18:00
1
It's generally a good idea to have amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
– Solomon Ucko
Dec 31 '18 at 3:26
|
show 4 more comments
This kind of programming exercice, despite its apparent simplicity, is a good opportunity to learn various things.
Style
Python has a Code Style guide called PEP 8. If you begin with Python, I highly recommend reading it every now and then and trying to apply it.
In your case, a few things could be improved regarding style:
- blank lines between the different branches of
if
are more an inconvenience from my point of view - variables should follow the
snake_case
naming convention (instead ofcamelCase
)
Builtin input
As you've noticed for the end of the function, the input
builtin takes an optional prompt
parameter. This could be used at the beginning of the function as well.
Duplicated code
A lot of code looks like the same line with minimal variations. Having duplicated code makes the code more tedious to read and harder to maintain (if you need to change something, you'll need to change it in many places). One of the principles of software programming is Don't Repeat Yourself (also written DRY).
In your case, we could store the body category in a variable and only print the ouput from a single place:
Chained comparison
This is very specific to Python but instead of body_mass_index > 30 and body_mass_index <= 35
, we can write: 30 < body_mass_index <= 35
using chained comparisons.
Magic numbers
Magic Numbers are usually frowned upon. In our case, one needs a bit of thinking to understand where the 12
and 0.025
come from. A better way to handle this is to store them in a variable with a meaningful name.
I am not quite sure about the best naming convention for names related to conversion constant. I've followed the names suggested by Solomon Ucko in the comments.
At this stage, we have the following code:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
body_mass_index = weight_in_kilo / (height_in_meter ** 2)
if body_mass_index < 15:
category = 'very severely underweight'
elif 15 <= body_mass_index <= 16 :
category = 'severely underweight'
elif 16 < body_mass_index <= 18.5:
category = 'underweight'
elif 18.5 < body_mass_index <= 25:
category = 'Normal(healthy weight)'
elif 25 < body_mass_index <= 30:
category = 'overweight'
elif 30 < body_mass_index <= 35:
category = 'moderately obese'
elif 35 < body_mass_index <= 40:
category = 'severely obese'
elif body_mass_index > 40:
category = 'very severely obese'
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
Which can still be improved.
Mutually exclusive conditions
Because of the way we check body_mass_index
, if it is under 15, we get into the first case so there is no need to check elif 15 <= body_mass_index
in the else
part. This is guaranteed to be always true. Similarly, half the checks have no effect.
Code organisation
To make the code easier to understand (and easier to reuse, to test, etc), it is a good habit to split in into smaller reusable chunks. In our case, defining functions could be a nice touch.
Disclaimer: Next paragraph can be a bit overwhelming for a beginner, do not worry if you do not fully get it. It highlights how to solve problems you may not be interested in yet but it is a good chance to do things properly.
Also, if we want to be able to actually reuse your functions, we want to be able to import
the file. Currently, if we do so, we get stuck into the parts asking for user inputs. Thus, the usual strategy is the following: split your code into 2 parts:
code defining functions/constants/classes/etc but without any side-effect or user interactions
code actually doing things (input/output, etc) behind an
if __name__ == "__main__":
guard. As pointed out by Solomon Ucko, it's generally a good idea to have this performed via amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
At this stage, we have:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
def convert_feet_to_meter(height_in_feet):
return height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
def get_body_mass_index(height_in_meter, weight_in_kilo):
return weight_in_kilo / (height_in_meter ** 2)
def get_category(body_mass_index):
if body_mass_index < 15:
return 'very severely underweight'
elif body_mass_index <= 16 :
return 'severely underweight'
elif body_mass_index <= 18.5:
return 'underweight'
elif body_mass_index <= 25:
return 'Normal(healthy weight)'
elif body_mass_index <= 30:
return 'overweight'
elif body_mass_index <= 35:
return 'moderately obese'
elif body_mass_index <= 40:
return 'severely obese'
else:
return 'very severely obese'
def main():
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = convert_feet_to_meter(height_in_feet)
body_mass_index = get_body_mass_index(height_in_meter, weight_in_kilo)
category = get_category(body_mass_index)
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
if __name__ == "__main__":
main()
Going further, a few more details could be improved.
String formatting
Python offers many tools to format strings so that you do not need to use string concatenations. You can refer to PyFormat.info for documentations and examples.
You could write:
print('Your BMI = %f You are %s.' % (body_mass_index, category))
Or the newer technique:
print('Your BMI = {} You are {}.'.format(body_mass_index, category))
Also, in Python 3.6, yet another soution was added: F-strings.
Data over code
This may be a bit overkill here but sometimes a lot of code can be replaced by a small amount of code working on a properly filled data structure. In our case, the get_category
function does the same thing for all categories: check the if we are under a given limit and if so, return the category name.
Disclaimer: Next part works under the assumption that body_mass_index < 15
should actually use <=
like the other cases.
# List of pairs (higher-limit, name) sorted
CATEGORIES = [
(15, 'very severely underweight'),
(16, 'severely underweight'),
(18.5, 'underweight'),
(25, 'Normal(healthy weight)'),
(30, 'overweight'),
(35, 'moderately obese'),
(40, 'severely obese'),
]
def get_category(body_mass_index):
for limit, name in CATEGORIES:
if body_mass_index <= limit:
return name
return 'very severely obese'
1
I haven't written python for a few years, but couldn't you only use if and return with a response function as soon as a condition is met?
– Džuris
Dec 30 '18 at 15:09
@Džuris I am not quite sure what you mean. Could you write somewhere ( pastebin.com ?) what you have in mind ?
– Josay
Dec 30 '18 at 15:13
sorry, I somehow misread a sample and was suggesting an idea similar to what's already there. Now that I read it properly on a computer, my question boils down to: Why do you needelif
(instead ofif
) andelse
in the second sample? Isn't it that a later condition is only reached if none of the previous are met and justif
(or nothing for the last case) would be enough?
– Džuris
Dec 30 '18 at 17:43
@Džuris Indeed, it would be the same. I kept the originalelif
because it didn't bother me. Then it is just a matter of personal preference. I have no strong opinion on this.
– Josay
Dec 30 '18 at 18:00
1
It's generally a good idea to have amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
– Solomon Ucko
Dec 31 '18 at 3:26
|
show 4 more comments
This kind of programming exercice, despite its apparent simplicity, is a good opportunity to learn various things.
Style
Python has a Code Style guide called PEP 8. If you begin with Python, I highly recommend reading it every now and then and trying to apply it.
In your case, a few things could be improved regarding style:
- blank lines between the different branches of
if
are more an inconvenience from my point of view - variables should follow the
snake_case
naming convention (instead ofcamelCase
)
Builtin input
As you've noticed for the end of the function, the input
builtin takes an optional prompt
parameter. This could be used at the beginning of the function as well.
Duplicated code
A lot of code looks like the same line with minimal variations. Having duplicated code makes the code more tedious to read and harder to maintain (if you need to change something, you'll need to change it in many places). One of the principles of software programming is Don't Repeat Yourself (also written DRY).
In your case, we could store the body category in a variable and only print the ouput from a single place:
Chained comparison
This is very specific to Python but instead of body_mass_index > 30 and body_mass_index <= 35
, we can write: 30 < body_mass_index <= 35
using chained comparisons.
Magic numbers
Magic Numbers are usually frowned upon. In our case, one needs a bit of thinking to understand where the 12
and 0.025
come from. A better way to handle this is to store them in a variable with a meaningful name.
I am not quite sure about the best naming convention for names related to conversion constant. I've followed the names suggested by Solomon Ucko in the comments.
At this stage, we have the following code:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
body_mass_index = weight_in_kilo / (height_in_meter ** 2)
if body_mass_index < 15:
category = 'very severely underweight'
elif 15 <= body_mass_index <= 16 :
category = 'severely underweight'
elif 16 < body_mass_index <= 18.5:
category = 'underweight'
elif 18.5 < body_mass_index <= 25:
category = 'Normal(healthy weight)'
elif 25 < body_mass_index <= 30:
category = 'overweight'
elif 30 < body_mass_index <= 35:
category = 'moderately obese'
elif 35 < body_mass_index <= 40:
category = 'severely obese'
elif body_mass_index > 40:
category = 'very severely obese'
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
Which can still be improved.
Mutually exclusive conditions
Because of the way we check body_mass_index
, if it is under 15, we get into the first case so there is no need to check elif 15 <= body_mass_index
in the else
part. This is guaranteed to be always true. Similarly, half the checks have no effect.
Code organisation
To make the code easier to understand (and easier to reuse, to test, etc), it is a good habit to split in into smaller reusable chunks. In our case, defining functions could be a nice touch.
Disclaimer: Next paragraph can be a bit overwhelming for a beginner, do not worry if you do not fully get it. It highlights how to solve problems you may not be interested in yet but it is a good chance to do things properly.
Also, if we want to be able to actually reuse your functions, we want to be able to import
the file. Currently, if we do so, we get stuck into the parts asking for user inputs. Thus, the usual strategy is the following: split your code into 2 parts:
code defining functions/constants/classes/etc but without any side-effect or user interactions
code actually doing things (input/output, etc) behind an
if __name__ == "__main__":
guard. As pointed out by Solomon Ucko, it's generally a good idea to have this performed via amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
At this stage, we have:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
def convert_feet_to_meter(height_in_feet):
return height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
def get_body_mass_index(height_in_meter, weight_in_kilo):
return weight_in_kilo / (height_in_meter ** 2)
def get_category(body_mass_index):
if body_mass_index < 15:
return 'very severely underweight'
elif body_mass_index <= 16 :
return 'severely underweight'
elif body_mass_index <= 18.5:
return 'underweight'
elif body_mass_index <= 25:
return 'Normal(healthy weight)'
elif body_mass_index <= 30:
return 'overweight'
elif body_mass_index <= 35:
return 'moderately obese'
elif body_mass_index <= 40:
return 'severely obese'
else:
return 'very severely obese'
def main():
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = convert_feet_to_meter(height_in_feet)
body_mass_index = get_body_mass_index(height_in_meter, weight_in_kilo)
category = get_category(body_mass_index)
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
if __name__ == "__main__":
main()
Going further, a few more details could be improved.
String formatting
Python offers many tools to format strings so that you do not need to use string concatenations. You can refer to PyFormat.info for documentations and examples.
You could write:
print('Your BMI = %f You are %s.' % (body_mass_index, category))
Or the newer technique:
print('Your BMI = {} You are {}.'.format(body_mass_index, category))
Also, in Python 3.6, yet another soution was added: F-strings.
Data over code
This may be a bit overkill here but sometimes a lot of code can be replaced by a small amount of code working on a properly filled data structure. In our case, the get_category
function does the same thing for all categories: check the if we are under a given limit and if so, return the category name.
Disclaimer: Next part works under the assumption that body_mass_index < 15
should actually use <=
like the other cases.
# List of pairs (higher-limit, name) sorted
CATEGORIES = [
(15, 'very severely underweight'),
(16, 'severely underweight'),
(18.5, 'underweight'),
(25, 'Normal(healthy weight)'),
(30, 'overweight'),
(35, 'moderately obese'),
(40, 'severely obese'),
]
def get_category(body_mass_index):
for limit, name in CATEGORIES:
if body_mass_index <= limit:
return name
return 'very severely obese'
This kind of programming exercice, despite its apparent simplicity, is a good opportunity to learn various things.
Style
Python has a Code Style guide called PEP 8. If you begin with Python, I highly recommend reading it every now and then and trying to apply it.
In your case, a few things could be improved regarding style:
- blank lines between the different branches of
if
are more an inconvenience from my point of view - variables should follow the
snake_case
naming convention (instead ofcamelCase
)
Builtin input
As you've noticed for the end of the function, the input
builtin takes an optional prompt
parameter. This could be used at the beginning of the function as well.
Duplicated code
A lot of code looks like the same line with minimal variations. Having duplicated code makes the code more tedious to read and harder to maintain (if you need to change something, you'll need to change it in many places). One of the principles of software programming is Don't Repeat Yourself (also written DRY).
In your case, we could store the body category in a variable and only print the ouput from a single place:
Chained comparison
This is very specific to Python but instead of body_mass_index > 30 and body_mass_index <= 35
, we can write: 30 < body_mass_index <= 35
using chained comparisons.
Magic numbers
Magic Numbers are usually frowned upon. In our case, one needs a bit of thinking to understand where the 12
and 0.025
come from. A better way to handle this is to store them in a variable with a meaningful name.
I am not quite sure about the best naming convention for names related to conversion constant. I've followed the names suggested by Solomon Ucko in the comments.
At this stage, we have the following code:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
body_mass_index = weight_in_kilo / (height_in_meter ** 2)
if body_mass_index < 15:
category = 'very severely underweight'
elif 15 <= body_mass_index <= 16 :
category = 'severely underweight'
elif 16 < body_mass_index <= 18.5:
category = 'underweight'
elif 18.5 < body_mass_index <= 25:
category = 'Normal(healthy weight)'
elif 25 < body_mass_index <= 30:
category = 'overweight'
elif 30 < body_mass_index <= 35:
category = 'moderately obese'
elif 35 < body_mass_index <= 40:
category = 'severely obese'
elif body_mass_index > 40:
category = 'very severely obese'
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
Which can still be improved.
Mutually exclusive conditions
Because of the way we check body_mass_index
, if it is under 15, we get into the first case so there is no need to check elif 15 <= body_mass_index
in the else
part. This is guaranteed to be always true. Similarly, half the checks have no effect.
Code organisation
To make the code easier to understand (and easier to reuse, to test, etc), it is a good habit to split in into smaller reusable chunks. In our case, defining functions could be a nice touch.
Disclaimer: Next paragraph can be a bit overwhelming for a beginner, do not worry if you do not fully get it. It highlights how to solve problems you may not be interested in yet but it is a good chance to do things properly.
Also, if we want to be able to actually reuse your functions, we want to be able to import
the file. Currently, if we do so, we get stuck into the parts asking for user inputs. Thus, the usual strategy is the following: split your code into 2 parts:
code defining functions/constants/classes/etc but without any side-effect or user interactions
code actually doing things (input/output, etc) behind an
if __name__ == "__main__":
guard. As pointed out by Solomon Ucko, it's generally a good idea to have this performed via amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
At this stage, we have:
INCHES_PER_FOOT = 12
METERS_PER_INCH = 0.0254
def convert_feet_to_meter(height_in_feet):
return height_in_feet * INCHES_PER_FOOT * METERS_PER_INCH
def get_body_mass_index(height_in_meter, weight_in_kilo):
return weight_in_kilo / (height_in_meter ** 2)
def get_category(body_mass_index):
if body_mass_index < 15:
return 'very severely underweight'
elif body_mass_index <= 16 :
return 'severely underweight'
elif body_mass_index <= 18.5:
return 'underweight'
elif body_mass_index <= 25:
return 'Normal(healthy weight)'
elif body_mass_index <= 30:
return 'overweight'
elif body_mass_index <= 35:
return 'moderately obese'
elif body_mass_index <= 40:
return 'severely obese'
else:
return 'very severely obese'
def main():
weight_in_kilo = float(input('Enter your weight in kilo:'))
height_in_feet = float(input('Enter your height in feet:'))
height_in_meter = convert_feet_to_meter(height_in_feet)
body_mass_index = get_body_mass_index(height_in_meter, weight_in_kilo)
category = get_category(body_mass_index)
print('Your BMI = ' + str(body_mass_index) + ' You are ' + category + '.')
input('Please press Enter to exit')
if __name__ == "__main__":
main()
Going further, a few more details could be improved.
String formatting
Python offers many tools to format strings so that you do not need to use string concatenations. You can refer to PyFormat.info for documentations and examples.
You could write:
print('Your BMI = %f You are %s.' % (body_mass_index, category))
Or the newer technique:
print('Your BMI = {} You are {}.'.format(body_mass_index, category))
Also, in Python 3.6, yet another soution was added: F-strings.
Data over code
This may be a bit overkill here but sometimes a lot of code can be replaced by a small amount of code working on a properly filled data structure. In our case, the get_category
function does the same thing for all categories: check the if we are under a given limit and if so, return the category name.
Disclaimer: Next part works under the assumption that body_mass_index < 15
should actually use <=
like the other cases.
# List of pairs (higher-limit, name) sorted
CATEGORIES = [
(15, 'very severely underweight'),
(16, 'severely underweight'),
(18.5, 'underweight'),
(25, 'Normal(healthy weight)'),
(30, 'overweight'),
(35, 'moderately obese'),
(40, 'severely obese'),
]
def get_category(body_mass_index):
for limit, name in CATEGORIES:
if body_mass_index <= limit:
return name
return 'very severely obese'
edited Jan 2 at 8:45
answered Dec 30 '18 at 10:01
JosayJosay
25.6k14087
25.6k14087
1
I haven't written python for a few years, but couldn't you only use if and return with a response function as soon as a condition is met?
– Džuris
Dec 30 '18 at 15:09
@Džuris I am not quite sure what you mean. Could you write somewhere ( pastebin.com ?) what you have in mind ?
– Josay
Dec 30 '18 at 15:13
sorry, I somehow misread a sample and was suggesting an idea similar to what's already there. Now that I read it properly on a computer, my question boils down to: Why do you needelif
(instead ofif
) andelse
in the second sample? Isn't it that a later condition is only reached if none of the previous are met and justif
(or nothing for the last case) would be enough?
– Džuris
Dec 30 '18 at 17:43
@Džuris Indeed, it would be the same. I kept the originalelif
because it didn't bother me. Then it is just a matter of personal preference. I have no strong opinion on this.
– Josay
Dec 30 '18 at 18:00
1
It's generally a good idea to have amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
– Solomon Ucko
Dec 31 '18 at 3:26
|
show 4 more comments
1
I haven't written python for a few years, but couldn't you only use if and return with a response function as soon as a condition is met?
– Džuris
Dec 30 '18 at 15:09
@Džuris I am not quite sure what you mean. Could you write somewhere ( pastebin.com ?) what you have in mind ?
– Josay
Dec 30 '18 at 15:13
sorry, I somehow misread a sample and was suggesting an idea similar to what's already there. Now that I read it properly on a computer, my question boils down to: Why do you needelif
(instead ofif
) andelse
in the second sample? Isn't it that a later condition is only reached if none of the previous are met and justif
(or nothing for the last case) would be enough?
– Džuris
Dec 30 '18 at 17:43
@Džuris Indeed, it would be the same. I kept the originalelif
because it didn't bother me. Then it is just a matter of personal preference. I have no strong opinion on this.
– Josay
Dec 30 '18 at 18:00
1
It's generally a good idea to have amain()
function and have the last two (non-blank) lines beif __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.
– Solomon Ucko
Dec 31 '18 at 3:26
1
1
I haven't written python for a few years, but couldn't you only use if and return with a response function as soon as a condition is met?
– Džuris
Dec 30 '18 at 15:09
I haven't written python for a few years, but couldn't you only use if and return with a response function as soon as a condition is met?
– Džuris
Dec 30 '18 at 15:09
@Džuris I am not quite sure what you mean. Could you write somewhere ( pastebin.com ?) what you have in mind ?
– Josay
Dec 30 '18 at 15:13
@Džuris I am not quite sure what you mean. Could you write somewhere ( pastebin.com ?) what you have in mind ?
– Josay
Dec 30 '18 at 15:13
sorry, I somehow misread a sample and was suggesting an idea similar to what's already there. Now that I read it properly on a computer, my question boils down to: Why do you need
elif
(instead of if
) and else
in the second sample? Isn't it that a later condition is only reached if none of the previous are met and just if
(or nothing for the last case) would be enough?– Džuris
Dec 30 '18 at 17:43
sorry, I somehow misread a sample and was suggesting an idea similar to what's already there. Now that I read it properly on a computer, my question boils down to: Why do you need
elif
(instead of if
) and else
in the second sample? Isn't it that a later condition is only reached if none of the previous are met and just if
(or nothing for the last case) would be enough?– Džuris
Dec 30 '18 at 17:43
@Džuris Indeed, it would be the same. I kept the original
elif
because it didn't bother me. Then it is just a matter of personal preference. I have no strong opinion on this.– Josay
Dec 30 '18 at 18:00
@Džuris Indeed, it would be the same. I kept the original
elif
because it didn't bother me. Then it is just a matter of personal preference. I have no strong opinion on this.– Josay
Dec 30 '18 at 18:00
1
1
It's generally a good idea to have a
main()
function and have the last two (non-blank) lines be if __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.– Solomon Ucko
Dec 31 '18 at 3:26
It's generally a good idea to have a
main()
function and have the last two (non-blank) lines be if __name__ == '__main__': main()
. This allows the interactivity to be triggered as needed.– Solomon Ucko
Dec 31 '18 at 3:26
|
show 4 more comments
One big refactoring that you could do is to remove all the if/else causes.
For example:
def compute_bmi(weight_in_kilo, height_in_feet):
STUPID_CONVERSION_CONSTANT = 12 * 0.025
return weight_in_kilo / ((height_in_feet * STUPID_CONVERSION_CONSTANT) ** 2)
def find_key_from_bmi(bmi):
keys = list(bmi_info.keys())
mins = [k if k <= bmi else 0 for k in keys]
return keys[mins.index(min(mins))]
def print_message(bmi):
print(f"Your BMI is {bmi} which means you are {bmi_info[find_key_from_bmi(bmi)]}.")
bmi_info = {
15: 'very severely underweight',
16: 'severely underweight',
18.5: 'underweight',
25: 'normal (healthy weight)',
30: 'overweight',
35: 'moderately obese',
40: 'severely obese',
}
print_message(compute_bmi(float(input("Enter you weight in kilo:")), float(input("Enter your height in feet:"))))
This scales to an arbitrary large number of categories (possibly automatically generated) without the need to write extra code.
Why do youimport numpy
? Also, it's probably best to define the constant outside the loop and with a descriptive name such asMETERS_PER_FOOT
.
– Solomon Ucko
Jan 1 at 2:33
Numpy was a leftover for no valid reason.
– Cedric H.
Jan 1 at 11:33
add a comment |
One big refactoring that you could do is to remove all the if/else causes.
For example:
def compute_bmi(weight_in_kilo, height_in_feet):
STUPID_CONVERSION_CONSTANT = 12 * 0.025
return weight_in_kilo / ((height_in_feet * STUPID_CONVERSION_CONSTANT) ** 2)
def find_key_from_bmi(bmi):
keys = list(bmi_info.keys())
mins = [k if k <= bmi else 0 for k in keys]
return keys[mins.index(min(mins))]
def print_message(bmi):
print(f"Your BMI is {bmi} which means you are {bmi_info[find_key_from_bmi(bmi)]}.")
bmi_info = {
15: 'very severely underweight',
16: 'severely underweight',
18.5: 'underweight',
25: 'normal (healthy weight)',
30: 'overweight',
35: 'moderately obese',
40: 'severely obese',
}
print_message(compute_bmi(float(input("Enter you weight in kilo:")), float(input("Enter your height in feet:"))))
This scales to an arbitrary large number of categories (possibly automatically generated) without the need to write extra code.
Why do youimport numpy
? Also, it's probably best to define the constant outside the loop and with a descriptive name such asMETERS_PER_FOOT
.
– Solomon Ucko
Jan 1 at 2:33
Numpy was a leftover for no valid reason.
– Cedric H.
Jan 1 at 11:33
add a comment |
One big refactoring that you could do is to remove all the if/else causes.
For example:
def compute_bmi(weight_in_kilo, height_in_feet):
STUPID_CONVERSION_CONSTANT = 12 * 0.025
return weight_in_kilo / ((height_in_feet * STUPID_CONVERSION_CONSTANT) ** 2)
def find_key_from_bmi(bmi):
keys = list(bmi_info.keys())
mins = [k if k <= bmi else 0 for k in keys]
return keys[mins.index(min(mins))]
def print_message(bmi):
print(f"Your BMI is {bmi} which means you are {bmi_info[find_key_from_bmi(bmi)]}.")
bmi_info = {
15: 'very severely underweight',
16: 'severely underweight',
18.5: 'underweight',
25: 'normal (healthy weight)',
30: 'overweight',
35: 'moderately obese',
40: 'severely obese',
}
print_message(compute_bmi(float(input("Enter you weight in kilo:")), float(input("Enter your height in feet:"))))
This scales to an arbitrary large number of categories (possibly automatically generated) without the need to write extra code.
One big refactoring that you could do is to remove all the if/else causes.
For example:
def compute_bmi(weight_in_kilo, height_in_feet):
STUPID_CONVERSION_CONSTANT = 12 * 0.025
return weight_in_kilo / ((height_in_feet * STUPID_CONVERSION_CONSTANT) ** 2)
def find_key_from_bmi(bmi):
keys = list(bmi_info.keys())
mins = [k if k <= bmi else 0 for k in keys]
return keys[mins.index(min(mins))]
def print_message(bmi):
print(f"Your BMI is {bmi} which means you are {bmi_info[find_key_from_bmi(bmi)]}.")
bmi_info = {
15: 'very severely underweight',
16: 'severely underweight',
18.5: 'underweight',
25: 'normal (healthy weight)',
30: 'overweight',
35: 'moderately obese',
40: 'severely obese',
}
print_message(compute_bmi(float(input("Enter you weight in kilo:")), float(input("Enter your height in feet:"))))
This scales to an arbitrary large number of categories (possibly automatically generated) without the need to write extra code.
edited Jan 1 at 11:33
answered Dec 30 '18 at 20:28


Cedric H.Cedric H.
1515
1515
Why do youimport numpy
? Also, it's probably best to define the constant outside the loop and with a descriptive name such asMETERS_PER_FOOT
.
– Solomon Ucko
Jan 1 at 2:33
Numpy was a leftover for no valid reason.
– Cedric H.
Jan 1 at 11:33
add a comment |
Why do youimport numpy
? Also, it's probably best to define the constant outside the loop and with a descriptive name such asMETERS_PER_FOOT
.
– Solomon Ucko
Jan 1 at 2:33
Numpy was a leftover for no valid reason.
– Cedric H.
Jan 1 at 11:33
Why do you
import numpy
? Also, it's probably best to define the constant outside the loop and with a descriptive name such as METERS_PER_FOOT
.– Solomon Ucko
Jan 1 at 2:33
Why do you
import numpy
? Also, it's probably best to define the constant outside the loop and with a descriptive name such as METERS_PER_FOOT
.– Solomon Ucko
Jan 1 at 2:33
Numpy was a leftover for no valid reason.
– Cedric H.
Jan 1 at 11:33
Numpy was a leftover for no valid reason.
– Cedric H.
Jan 1 at 11:33
add a comment |
Well, you could refactor the print part and extract it to a function like this:
def printBMIMessage(bodyMassIndex, message):
print('Your BMI = ' + str(bodyMassIndex) + ' ' + message)
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
printBMIMessage(bodyMassIndex, 'You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
printBMIMessage(bodyMassIndex, 'You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
printBMIMessage(bodyMassIndex, 'You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
printBMIMessage(bodyMassIndex, 'You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
printBMIMessage(bodyMassIndex, 'You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
printBMIMessage(bodyMassIndex, 'You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
printBMIMessage(bodyMassIndex, 'You are severely obese.')
elif bodyMassIndex > 40:
printBMIMessage(bodyMassIndex, 'You are very severely obese.')
input('Please press Enter to exit')
I don't really like the control flow of theprintBMIMessage
function because it allows to doprintBMIMessage(40, 'You are underweight')
.
– svavil
Dec 30 '18 at 19:59
add a comment |
Well, you could refactor the print part and extract it to a function like this:
def printBMIMessage(bodyMassIndex, message):
print('Your BMI = ' + str(bodyMassIndex) + ' ' + message)
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
printBMIMessage(bodyMassIndex, 'You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
printBMIMessage(bodyMassIndex, 'You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
printBMIMessage(bodyMassIndex, 'You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
printBMIMessage(bodyMassIndex, 'You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
printBMIMessage(bodyMassIndex, 'You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
printBMIMessage(bodyMassIndex, 'You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
printBMIMessage(bodyMassIndex, 'You are severely obese.')
elif bodyMassIndex > 40:
printBMIMessage(bodyMassIndex, 'You are very severely obese.')
input('Please press Enter to exit')
I don't really like the control flow of theprintBMIMessage
function because it allows to doprintBMIMessage(40, 'You are underweight')
.
– svavil
Dec 30 '18 at 19:59
add a comment |
Well, you could refactor the print part and extract it to a function like this:
def printBMIMessage(bodyMassIndex, message):
print('Your BMI = ' + str(bodyMassIndex) + ' ' + message)
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
printBMIMessage(bodyMassIndex, 'You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
printBMIMessage(bodyMassIndex, 'You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
printBMIMessage(bodyMassIndex, 'You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
printBMIMessage(bodyMassIndex, 'You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
printBMIMessage(bodyMassIndex, 'You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
printBMIMessage(bodyMassIndex, 'You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
printBMIMessage(bodyMassIndex, 'You are severely obese.')
elif bodyMassIndex > 40:
printBMIMessage(bodyMassIndex, 'You are very severely obese.')
input('Please press Enter to exit')
Well, you could refactor the print part and extract it to a function like this:
def printBMIMessage(bodyMassIndex, message):
print('Your BMI = ' + str(bodyMassIndex) + ' ' + message)
print('Enter your weight in kilo:')
weightInKilo = float(input())
print('Enter your height in feet:')
heightInFeet = float(input())
heightInMeter = heightInFeet * 12 * 0.025
bodyMassIndex = weightInKilo / (heightInMeter ** 2)
if bodyMassIndex < 15:
printBMIMessage(bodyMassIndex, 'You are very severely underweight.')
elif bodyMassIndex >= 15 and bodyMassIndex <= 16 :
printBMIMessage(bodyMassIndex, 'You are severely underweight.')
elif bodyMassIndex > 16 and bodyMassIndex <= 18.5:
printBMIMessage(bodyMassIndex, 'You are underweight.')
elif bodyMassIndex > 18.5 and bodyMassIndex <= 25:
printBMIMessage(bodyMassIndex, 'You are Normal(healthy weight).')
elif bodyMassIndex > 25 and bodyMassIndex <= 30:
printBMIMessage(bodyMassIndex, 'You are overweight.')
elif bodyMassIndex > 30 and bodyMassIndex <= 35:
printBMIMessage(bodyMassIndex, 'You are moderately obese.')
elif bodyMassIndex > 35 and bodyMassIndex <= 40:
printBMIMessage(bodyMassIndex, 'You are severely obese.')
elif bodyMassIndex > 40:
printBMIMessage(bodyMassIndex, 'You are very severely obese.')
input('Please press Enter to exit')
answered Dec 30 '18 at 9:43
Shai AharoniShai Aharoni
1212
1212
I don't really like the control flow of theprintBMIMessage
function because it allows to doprintBMIMessage(40, 'You are underweight')
.
– svavil
Dec 30 '18 at 19:59
add a comment |
I don't really like the control flow of theprintBMIMessage
function because it allows to doprintBMIMessage(40, 'You are underweight')
.
– svavil
Dec 30 '18 at 19:59
I don't really like the control flow of the
printBMIMessage
function because it allows to do printBMIMessage(40, 'You are underweight')
.– svavil
Dec 30 '18 at 19:59
I don't really like the control flow of the
printBMIMessage
function because it allows to do printBMIMessage(40, 'You are underweight')
.– svavil
Dec 30 '18 at 19:59
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210592%2fbmi-calculator-in-python-using-if-statements%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
FYI, some 2017 research indicates that waist-to-height ratio is a better obesity index when predicting 'metabolic syndrome' for individuals. You could extend your code to return that information as well, or at least note in the output that the code judges an 'obese' condition based only on BMI, out of multiple possible obesity indices.
– user117529
Dec 31 '18 at 23:50