Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with simple Python code

Tags:

python

I have a simple python (version 2.7.3) code that has an output that I can't figure out. The code prompts the user for a score (and will continue to do so if the input is anything other than a number from 0 to 1), determines the letter grade, and then exits. The code is as follows:

def calc_grade():
    try:
        score = float(raw_input("Enter a score: "))
        if score > 1.0:
            print "Error: Score cannot be greater than 1."
            calc_grade()
    except:
        print "Error: Score must be a numeric value from 0 to 1."
        calc_grade()

    print "\nthe score is: %s" % (score)
    if score >= 0.9:
        print "A"
    elif score >= 0.8:
        print "B"
    elif score >= 0.7:
        print "C"
    elif score >= 0.6:
        print "D"
    else:
        print "F"
    return 0
calc_grade()

If I run this script an try the inputs: 1.5, h, 0.8, then I get the following output:

Enter a score: 1.5
Error: Score cannot be greater than 1.
Enter a score: h
Error: Score must be a numeric value from 0 to 1.
Enter a score: 0.8

the score is: 0.8
B
Error: Score must be a numeric value from 0 to 1.
Enter a score: 0.7

the score is: 0.7
C

the score is: 1.5
A

As you can see, after entering a valid value (0.8), the script prints out the correct grade (B), but then script doesn't end as I expect it to. Instead, it prints out the error message for a non-numeric value, and then prompts the user to enter a score again. If I enter another valid score (0.7 in this case), then script prints out the correct grade (C), and then prints out the first incorrect input (1.5) along with its grade (A).

I can't, for the life of me, figure out what's causing this, "functionality". Any suggestions?

like image 414
Shaun Avatar asked Mar 29 '26 15:03

Shaun


2 Answers

On any error that occurs, you call calc_grade recursively again, so if you entered an invalid input, you'd have several calls. Instead, you should handle faulty errors iteratively:

def calc_grade():
    score = None
    while score is None:     
        try:
            score = float(raw_input("Enter a score: "))
            if score > 1.0:
                print "Error: Score cannot be greater than 1."
                score = None
        except:
            print "Error: Score must be a numeric value from 0 to 1."

    # If we reached here, score is valid,
    # continue with the rest of the code
like image 71
Mureinik Avatar answered Mar 31 '26 03:03

Mureinik


Here's what happened:

When you passed your function the value "h", the casting of "h" to float failed, which threw a ValueError. Your except statement caught the error, and then called calcGrade() again. This new call was given an argument of .8, and returned normally. When the .8 call returned, it returned control back to the call the had received "h" as an argument. That call then proceeded to execute its next instruction: print "\nthe score is: %s" % (score). Since the cast to float had failed, score was never assigned. Therefore, that call to calcGrade() throws an UnboundLocalError, which is then caught by its caller, which is the instance of calcGrade() that was passed the value 1.5 (as @ZackTanner pointed out). Recall that the "h" call was called from inside the try block.

like image 27
Sam Hazleton Avatar answered Mar 31 '26 04:03

Sam Hazleton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!