简单Python代码出错

时间:2015-06-24 22:27:10

标签: python

我有一个简单的python(版本2.7.3)代码,它有一个我无法弄清楚的输出。代码提示用户输入分数(如果输入不是0到1之间的数字,则会继续这样做),确定字母等级,然后退出。代码如下:

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()

如果我运行此脚本,请尝试输入: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

如您所见,在输入有效值(0.8)后,脚本会输出正确的等级(B),但脚本不会像我预期的那样结束。相反,它会打印出非数字值的错误消息,然后提示用户再次输入分数。如果我输入另一个有效分数(在这种情况下为0.7),则脚本会打印出正确的分数(C),然后打印出第一个不正确的输入(1.5)及其等级(A)。

对于我的生活,我不能弄清楚是什么造成了这种“功能”。有什么建议吗?

5 个答案:

答案 0 :(得分:7)

在发生任何错误时,您再次以递归方式调用calc_grade,因此如果输入的输入无效,则需要多次调用。相反,您应该迭代地处理错误的错误:

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

答案 1 :(得分:1)

以下是发生的事情:

当你传递你的函数值" h"时," h"到float失败,引发了一个ValueError。您的except语句捕获了错误,然后再次调用calcGrade()。这个新的调用给出了.8的参数,并正常返回。当.8呼叫返回时,它将控制权返回给已收到的呼叫" h"作为一个论点。然后该调用继续执行下一条指令:print "\nthe score is: %s" % (score)。由于施放到浮动失败,因此从未分配得分。因此,对calcGrade()的调用会抛出UnboundLocalError,然后由其调用者捕获,调用者是传递值1.5的calcGrade()实例(如@ZackTanner指出的那样)。回想一下" h"调用是从try块内调用的。

答案 2 :(得分:0)

Recusion正在咬你,因为在递归后你的函数中有额外的代码。 @Mureink的答案是处理这个问题的有效方法。另一种方法是使数据输入操作成为它自己的功能:

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()

当用户输入有效值时,此技术返回输入的值。如果没有,则返回调用get_input()的值。这会堆叠所有递归,准备返回返回给它们的任何内容。当用户最终输入有效响应时,整个递归堆栈将折叠,返回用户输入的有效答案。

get_input()calc_grade的来电将一直处理,直到用户输入有效答案为止。那时get_input将停止处理,并将有效的用户输入返回calc_grade calc_grade进行处理。

答案 3 :(得分:0)

您忘记了递归不会终止先前对函数的调用。因此,当您在错误时调用calc_grade()时,您会返回到原来的calc_grade()print "the score is:",这就是它打印几次的原因。

现在,为了修复你的代码,我只想添加一些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不需要你在返回后写任何东西,你可以用它来简单地退出函数。

另外,我建议使用str.format作为%格式。

如果不过多修改代码,我就是这样做的:

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()

答案 4 :(得分:0)

首先,您无法在calc_grade()内拨打电话。这会产生一堆错误。您只能调用一次,但可以根据需要多次打印。 第二tryexcept可能不是最好的方法。尝试制作class并从那里制作功能。每次代码完成运行时,都会运行tryexcept第三,如果您在这些数字之间运行一个数字,它将print最大值之前的所有字母。我有类似于你的代码,它计算3个人的分数。这是一个帮助您更好地理解错误和例外的网站。 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))