我有一个简单的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)。
对于我的生活,我不能弄清楚是什么造成了这种“功能”。有什么建议吗?
答案 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()
内拨打电话。这会产生一堆错误。您只能调用一次,但可以根据需要多次打印。 第二,try
和except
可能不是最好的方法。尝试制作class
并从那里制作功能。每次代码完成运行时,都会运行try
和except
。 第三,如果您在这些数字之间运行一个数字,它将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))