简体   繁体   English

Python 异常处理 - BMI 计算器

[英]Python Exception Handling - BMI CALCULATOR

I am coding a BMI calculator in python and wanted to add exception handling.我正在 python 中编写一个 BMI 计算器,并想添加异常处理。 I created two functions 1. a height converter that converts the height to feet or meters depending on the user's input, and a weight converter that converts the user's weight to kg or pounds depending on the input.我创建了两个函数 1. 一个高度转换器,根据用户的输入将高度转换为英尺或米,以及一个重量转换器,根据输入将用户的体重转换为公斤或磅。 The def height_converter(h) and weight_converter(w) functions don't restart when the user types in the wrong input, unlike the codes below it which asks only for the weight and height.当用户输入错误的输入时,def height_converter(h) 和 weight_converter(w) 函数不会重新启动,这与下面的代码不同,它只询问体重和高度。 Also, the BMI variable returns an error, I don't know what to do again另外,BMI变量返回错误,我不知道该怎么办了

# BMI CALCULATOR IN PYTHON
import os
from datetime import datetime
# define our clear function
def clear():
    # for windows
    if os.name == 'nt':
        os.system('cls')
    # for mac and linux(here, os.name is 'posix')
    else:
        _ = os.system('clear')
def weight_converter(w):
    while True:
        try:
            global converted
            converted = 0
            weight_unit = input("What is the weight unit Kgs or Lbs: ")
            if weight_unit.upper() == "KG":
                converted = w / 1
                print("weight in kg is: ", converted)
            elif weight_unit.upper() == "LBS":
                converted = w / 2.2
                print("weight in kg is: ", converted)
            else:
                raise ValueError(weight_unit)
            break
        except (ValueError, IOError, IndexError):
            print("ERROR")
            return converted
def height_converter(h):
    while True:
        try:
            height_unit = input("what is the height unit meters or feet: ")
            if height_unit.upper() == "METERS":
                converted = h / 1
                print("height in meters is: ", converted)
            elif height_unit.upper() == "FEET":
                converted = h / 3.281
                print("height in meters is: ", converted)
            break
        except(ValueError,IOError,IndexError):
            print("ERROR")
        return converted
while True:
    try:
        age = input("How old are you? ")
        age = int(age)

        weight = input("What is your weight: ")
        weight = float(weight)
        wconverted = weight_converter(weight)
      
        height = input("What is your height: ")
        height = float(height)
        hconverted = height_converter(height)
        break
    except ValueError:
        # os.system(clock_settime)
        print("No valid integer! Please try again ...")
        clear()
BMI = float(wconverted / (hconverted ** 2))
print("Your BMI is: ", BMI, "as of ", date) 
print("You are using a", os.name, "system")

In your weight_converter function you are only going to return the converted value when the user enters bad input.在您的 weight_converter function 中,您只会在用户输入错误输入时返回转换后的值。 In Python the indention determines in which code block the statement will belong.在 Python 中,缩进决定了语句属于哪个代码块。 You need to put the return statement at the same indention level as your while True: That puts it outside the while loop and it'll basically happen after one of you breaks.您需要将 return 语句放在与 while True 相同的缩进级别:这将它放在 while 循环之外,并且它基本上会在你们中的一个人休息后发生。

The height_converter function has a similar problem. height_converter function 也有类似的问题。

Also you only raise the ValueError in one of these functions and since you catch them in the except block they will not propagate up to the caller.此外,您仅在其中一个函数中引发 ValueError ,并且由于您在 except 块中捕获它们,因此它们不会传播到调用者。

Exception handling for this code seems like unnecessary added complexity.这段代码的异常处理似乎增加了不必要的复杂性。 Raising a ValueError simply to make the next line of code do something different is overkill and confusing.仅仅为了让下一行代码做一些不同的事情而引发 ValueError 是矫枉过正和令人困惑的。 Here is a much simpler version of your weight_converter function.这是一个更简单的 weight_converter function 版本。

def weight_converter(w):
    while True:
        weight_unit = input("What is the weight unit Kgs or Lbs: ")
        if weight_unit.upper() == "KG":
            conversion = 1.0
            break
        elif weight_unit.upper() == "LBS":
            conversion = 2.2
            break
        else
            print("ERROR")
    converted = w / conversion
    print("weight in kg is: ", converted)
    return converted

Uncaught exceptions propagate up the call stack until they are caught by an except block.未捕获的异常沿调用堆栈向上传播,直到它们被 except 块捕获。 If they are not caught they cause the interpreter to halt the program and usually print a stack trace.如果它们没有被捕获,它们会导致解释器停止程序并通常打印堆栈跟踪。 If this code causes exceptions they will be caught by the exception handler that you have in the caller.如果此代码导致异常,它们将被调用者中的异常处理程序捕获。 If you catch them in this function they will never make it up to the caller.如果您在此 function 中抓住它们,它们将永远无法弥补调用者的损失。

Testing out your code, in the conversion functions, the return operation at the end of the code blocks were not actually being executed because of where it logically resided within the indentation of the code block.测试您的代码,在转换函数中,代码块末尾的返回操作实际上并未被执行,因为它在逻辑上位于代码块的缩进中。 So, you were effectively returning a "None" to the statements calling those functions.因此,您实际上是在向调用这些函数的语句返回“无”。

With that in mind, following is your code with some tweaks to return a converted value from the weight and height conversion functions.考虑到这一点,以下是您的代码,其中进行了一些调整,以从体重和身高转换函数返回转换后的值。

# BMI CALCULATOR IN PYTHON
import os
from datetime import date     # FYI, I revised this a bit as well for the date
# define our clear function
def clear():
    # for windows
    if os.name == 'nt':
        os.system('cls')
    # for mac and linux(here, os.name is 'posix')
    else:
        _ = os.system('clear')
def weight_converter(w):
    while True:
        try:
            global converted
            converted = 0
            weight_unit = input("What is the weight unit Kgs or Lbs: ")
            if weight_unit.upper() == "KG":
                converted = w / 1
                print("weight in kg is: ", converted)
                return converted            # Made sure a decimal value was being returned
            elif weight_unit.upper() == "LBS":
                converted = w / 2.2
                print("weight in kg is: ", converted)
                return converted            # Same here
            else:
                raise ValueError(weight_unit)
            break
        except (ValueError, IOError, IndexError):
            print("ERROR")
            return 0.0
def height_converter(h):
    while True:
        try:
            height_unit = input("what is the height unit meters or feet: ")
            if height_unit.upper() == "METERS":
                converted = h / 1
                print("height in meters is: ", converted)
                return converted            # And here
            elif height_unit.upper() == "FEET":
                converted = h / 3.281
                print("height in meters is: ", converted)
                return converted            # And finally here
            break
        except(ValueError,IOError,IndexError):
            print("ERROR")
        return 1.0
while True:
    try:
        age = input("How old are you? ")
        age = int(age)

        weight = input("What is your weight: ")
        weight = float(weight)
        wconverted = weight_converter(weight)
      
        height = input("What is your height: ")
        height = float(height)
        hconverted = height_converter(height)
        break
    except ValueError:
        # os.system(clock_settime)
        print("No valid integer! Please try again ...")
        clear()
BMI = float(wconverted / (hconverted ** 2))
print("Your BMI is: ", BMI, "as of ", date.today())     # You had not defined the variable "date"
print("You are using a", os.name, "system")

I applied a brute force method to make sure a value was being returned.我应用了蛮力方法来确保返回值。 Alternatively, you might refine that last return in your function block to only have one return, but I just wanted to avoid possible scope issues in providing a quick tweak.或者,您可以将 function 块中的最后一个返回改进为只有一个返回,但我只是想避免在提供快速调整时可能出现的 scope 问题。

That produced the following sample results.这产生了以下示例结果。

@Una:~/Python_Programs/BMI$ python3 Calculator.py 
How old are you? 66
What is your weight: 170
What is the weight unit Kgs or Lbs: lbs
weight in kg is:  77.27272727272727
What is your height: 5.83333
what is the height unit meters or feet: feet
height in meters is:  1.7779122218835721
Your BMI is:  24.445876294351564 as of  2022-09-06
You are using a posix system

Give that a try.试试看。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM