[英]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. 其次 , try
, except
可能不是最好的方法。 Try making a class
and making functions from there. 尝试class
并从那里开始制作功能。 try
and except
will be run every time your code finished running. try
, except
每次代码完成运行时都会运行。 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.