0

I am doing an exercise involving exploring the use of exception handling using try-except in Python. I am using them to check if a user entered value is a float or something else (e.g. a string). If the value is not a float, the exception is triggered and the function is recursively called. This works, but when I print and return the value, the value is a list of both the float and the string, despite attempts to initialize to a float both locally and globally. I am new to Python and I am admittedly not used to its nuances when compared to C/C++. I am probably missing something trivial, but I can't determine the cause. The program is as follows:

def check_cost():
    fuel_cost = 0.0
    fuel_cost = input("What is the cost per unit fuel (in $ per gallons)? ")
    try:
        fuel_cost = float(fuel_cost)
    except ValueError as e:
        print("\nThe value has to be numeric. Please try again.")
        check_cost()
    print(fuel_cost)
    return fuel_cost

def check_distance():
    work_distance = 0.0
    work_distance = input("What is the one-way distance to work (in miles)? ")
    try:
        work_distance = float(work_distance)
    except ValueError as e:
        print("\nThe value has to be numeric. Please try again.")
        check_distance()
    print(work_distance)
    return work_distance

def check_level():
    fuel_level = 0.0
    fuel_level = input("What is the current amount of fuel in your tank (in gallons)? ")
    try:
        fuel_level = float(fuel_level)
    except ValueError as e:
        print("\nThe value has to be numeric. Please try again.")
        check_level()
    print(fuel_level)
    return fuel_level

def check_rate():
    consumption_rate = 0.0
    consumption_rate = input("What is your fuel economy (in miles per gallon)? ")
    try:
        consumption_rate = float(consumption_rate)
    except ValueError as e:
        print("\nThe value has to be numeric. Please try again.")
        check_rate()
    print(consumption_rate)
    return consumption_rate  

fuel_cost = 0.0
work_distance = 0.0
fuel_level = 0.0
consumption_rate = 0.0

name = input("What is your user name? ")

print("\nHello, %s! Let's get started!" % name)

check = True

while check:
    # cost per unit of fuel
    #fuel_cost = float(input("What is the cost per unit fuel (in $ per gallons)? "))
    fuel_cost = check_cost()
    # one-way distance to work
    #work_distance = float(input("What is the one-way distance to work (in miles)? "))
    work_distance = check_distance()
    # current amount of fuel in gas tank
    #fuel_level = float(input("What is the current amount of fuel in your tank (in gallons)? "))
    fuel_level = check_level()
    # drivable distance per unit of fuel
    #consumption_rate = float(input("What is your fuel economy (in miles per gallon)? "))
    consumption_rate = check_rate()
    # acceptable level of fuel:
    threshold = work_distance / consumption_rate

loop_1 = True

while loop_1:
    review = input("Would you like to review the values? (Y/N) ")
    if review == 'Y' or review == 'y':
        print("\nfuel cost = %.2f" % fuel_cost)
        print("work distance = %.2f" % work_distance)
        print("fuel level = %.2f" % fuel_level)
        print("consumption rate = %.2f" % consumption_rate)
        loop_1 = False
    elif review == 'N' or review == 'n':
        print("\nOkay, continuing...")
        loop_1 = False
    else:
        print("\nInvalid input. Please enter either of Y/N")

loop_2 = True

while loop_2:
    question = input("Would you like to re-enter these values? (Y/N)")
    if question == 'Y' or question == 'y':
        check = True
        loop_2 = False
    elif question == 'N' or question == 'n':
        check = False
        loop_2 = False
    else:
        print("\nInvalid input. Please enter either of Y/N")

# Reporting Strings:
low = '\nYou will not make it to work without refueling first!\n'
exact = '\nYou have just enough fuel to get to work, but will not make it home.\n'
some_extra ='\nYou will need to refuel in the near future...\n'
surplus = '\nYou have plenty of fuel, have a safe drive to work today!\n'

if fuel_level < threshold:
    print(low)
elif fuel_level == threshold:
    print(exact)
elif fuel_level > threshold and fuel_level < threshold+1 :
    print(some_extra)
else:
    print(surplus)

And the print output is as follows:

What is your user name? Leigh

Hello, Leigh! Let's get started!

What is the cost per unit fuel (in $ per gallons)? five

The value has to be numeric. Please try again.

What is the cost per unit fuel (in $ per gallons)? 5
5.0
five

What is the one-way distance to work (in miles)? five

The value has to be numeric. Please try again.

What is the one-way distance to work (in miles)? 5
5.0
five

What is the current amount of fuel in your tank (in gallons)? five

The value has to be numeric. Please try again.

What is the current amount of fuel in your tank (in gallons)? 5
5.0
five

What is your fuel economy (in miles per gallon)? five

The value has to be numeric. Please try again.

What is your fuel economy (in miles per gallon)? 5
5.0
five

Traceback (most recent call last):

threshold = work_distance / consumption_rate

TypeError: unsupported operand type(s) for /: 'str' and 'str'
Leigh K
  • 561
  • 6
  • 20

1 Answers1

1

In future, please take the time to post a minimal statement of your problem. In other words, debug your code and find the specific segment that is causing a problem. Often you will find the solution presents itself in the process.

The problem is that your recursive function does not work as you expect due to scoping. In your check_rate function, check_rate() is run from within the except loop and its results then discarded as you do not store them anywhere. Then the function continues and uses the old string variable ("five").

Here is the correct way to define your function:

def check_rate():
    while True:
        try:
            consumption_rate = float(input("What is your fuel economy (in miles per gallon)? "))
        except ValueError as e:
            print("\nThe value has to be numeric. Please try again.")
            continue
        else:
            break
    return consumption_rate

check_rate()

See also: Asking the user for input until they give a valid response

jpp
  • 159,742
  • 34
  • 281
  • 339