简体   繁体   English

简单的Python代码出错

[英]Error with simple Python code

I have a simple python (version 2.7.3) code that has an output that I can't figure out. 我有一个简单的python(版本2.7.3)代码,有一个我无法弄清楚的输出。 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. 代码提示用户输入分数(如果输入不是0到1之间的数字,则会继续这样做),确定字母等级,然后退出。 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: 如果我运行此脚本,请尝试输入:1.5,h,0.8,然后我得到以下输出:

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. 如您所见,在输入有效值(0.8)后,脚本会输出正确的等级(B),但脚本不会像我预期的那样结束。 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). 如果我输入另一个有效分数(在这种情况下为0.7),则脚本打印出正确的等级(C),然后打印出第一个错误输入(1.5)及其等级(A)。

I can't, for the life of me, figure out what's causing this, "functionality". 在我的生活中,我不能弄清楚是什么导致了这个“功能”。 Any suggestions? 有什么建议么?

On any error that occurs, you call calc_grade recursively again, so if you entered an invalid input, you'd have several calls. 在发生任何错误时,再次递归调用calc_grade ,因此如果输入了无效输入,则会有多次调用。 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

Here's what happened: 这是发生的事情:

When you passed your function the value "h", the casting of "h" to float failed, which threw a ValueError. 当您传递函数值“h”时,“h”的转换为float失败,从而引发了ValueError。 Your except statement caught the error, and then called calcGrade() again. 您的except语句捕获了错误,然后再次调用calcGrade() This new call was given an argument of .8, and returned normally. 这个新的调用给出了.8的参数,并正常返回。 When the .8 call returned, it returned control back to the call the had received "h" as an argument. 当.8调用返回时,它将控制权返回给已经收到“h”作为参数的调用。 That call then proceeded to execute its next instruction: print "\\nthe score is: %s" % (score) . 然后该调用继续执行下一条指令: 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). 因此,对calcGrade()调用抛出一个UnboundLocalError ,然后由其调用者捕获,调用者是传递值1.5的calcGrade()实例(如@ZackTanner指出的那样)。 Recall that the "h" call was called from inside the try block. 回想一下,在try块内部调用了“h”调用。

Recusion is biting you because you have additional code in your function after the recursion. Recusion正在咬你,因为在递归后你的函数中有额外的代码。 @Mureink 's answer is a valid way to handle this. @Mureink的答案是处理这个问题的有效方法。 Another is to make the data input action it's own function: 另一个是使数据输入动作它自己的功能:

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

def calc_grade():
    score = get_input()
    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()

This technique returns the entered value when the user enters a valid value. 当用户输入有效值时,此技术返回输入的值。 When they do not, it returns the value of calling get_input() . 如果没有,则返回调用get_input()的值。 this stacks up all the recursions ready to return whatever gets returned to them. 这会堆叠所有递归,准备返回返回给它们的任何内容。 When the user finally enters a valid response, the entire recursion stack collapses returning the valid answer that the user entered. 当用户最终输入有效响应时,整个递归堆栈将折叠,返回用户输入的有效答案。

The call to get_input() within calc_grade will process until the user enters a valid answer. calc_grade调用get_input()将一直处理,直到用户输入有效的答案。 At that time get_input will cease processing and return that valid user input to calc_grade for calc_grade to do its processing. 那时get_input将停止处理并将有效的用户输入返回到calc_grade以便calc_grade进行处理。

You are forgetting that recursion doesn't terminate the previous call to the function. 您忘记了递归不会终止先前对函数的调用。 So when you call calc_grade() at the error you then return to the original calc_grade() to print "the score is:" and that's why it prints several times. 因此,当您在错误处调用calc_grade()时,您将返回到原始calc_grade()print "the score is:" ,这就是它打印几次的原因。

Now, to fix your code, I'd just add some returs: 现在,为了修复你的代码,我只想添加一些returs:

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()
            return
    except:
        print "Error: Score must be a numeric value from 0 to 1."
        calc_grade()
        return    
    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"
calc_grade()

Python doesn't require you to write anything after return, you can use it to simply exit the function. Python不需要你在返回后写任何东西,你可以用它来简单地退出函数。

Also I recommend using str.format as oposed to the % formatting. 另外,我建议使用str.format作为%格式。

This is how I'd do it without modifying your code too much: 这就是我在不修改代码的情况下这样做的方法:

def calc_grade():
    try:
        score = float(raw_input("Enter a score: "))
        if score > 1.0:
            raise TypeError
    except ValueError:
        print "Error: Score must be a numeric value from 0 to 1."
    except TypeError:
        print "Error: Score cannot be greater than 1."
    except:
        print "Error: Unexpected error, try again."
    else:
        if score >= 0.9:
            score = "A"
        elif score >= 0.8:
            score = "B"
        elif score >= 0.7:
            score = "C"
        elif score >= 0.6:
            score = "D"
        else:
            score = "F"
        print "the score is: {}".format(score)
        return
    calc_grade()

calc_grade()

First , you cannot call inside calc_grade() . 首先 ,你不能在calc_grade()内部调用。 That will run a bunch of errors. 这会产生一堆错误。 You can only call it once, but you can print it as many times as you want. 您只能调用一次,但可以根据需要多次打印。 Second , try and except might not be the best way to do it. 其次tryexcept可能不是最好的方法。 Try making a class and making functions from there. 尝试class并从那里开始制作功能。 try and except will be run every time your code finished running. tryexcept每次代码完成运行时都会运行。 Third , if you run a number between any of those numbers it will print all the letter before the maximum. 第三 ,如果你在任何一个数字之间运行一个数字,它将在最大值之前print所有字母。 I have code that is similar to yours, it calculates 3 peoples scores. 我有类似于你的代码,它计算3个人的分数。 Here is a website to help you better understand Errors and Exceptions. 这是一个帮助您更好地理解错误和例外的网站。 https://docs.python.org/2/tutorial/errors.html https://docs.python.org/2/tutorial/errors.html

Here is my code
    lloyd = {
        "name": "Lloyd",
        "homework": [90.0, 97.0, 75.0, 92.0],
        "quizzes": [88.0, 40.0, 94.0],
        "tests": [75.0, 90.0]
    }
    alice = {
        "name": "Alice",
        "homework": [100.0, 92.0, 98.0, 100.0],
        "quizzes": [82.0, 83.0, 91.0],
        "tests": [89.0, 97.0]
    }
    tyler = {
        "name": "Tyler",
        "homework": [0.0, 87.0, 75.0, 22.0],
        "quizzes": [0.0, 75.0, 78.0],
        "tests": [100.0, 100.0]
    }

# Add your function below! def average(numbers): total = sum(numbers) total = float(total) return total/len(numbers) def get_average(student): homework_ave=average(student["homework"]) quizzes_ave=average(student["quizzes"]) tests_ave=average(student["tests"]) return 0.1 * average(student["homework"]) + 0.3 * average(student["quizzes"]) + 0.6 * average(student["tests"]) def get_letter_grade(score): if 90 <= score: return "A" elif 80 <= score: return "B" elif 70 <= score: return "C" elif 60 <= score: return "D" else: return "F" print get_letter_grade(get_average(lloyd)) def get_class_average(students): results = [] for student in students: results.append(get_average(student)) return average(results) students = [lloyd, alice, tyler] print get_class_average(students) print get_letter_grade(get_class_average(students))

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

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