为什么在条件语句中调用变量两次对于范围值是必需的?



所以,我解决了下面的代码最初不起作用的代码问题,但我想解释一下为什么我的原始代码没有按预期工作。如果我在 if/elif/else 部分中指定了一次变量"grade"并将"and"运算符设置为我需要让它工作的参数,难道不应该在不使用它两次的情况下将 grade 与两者进行比较吗?

这是不起作用的代码

#  if and elif statements for calculating grade score letters
def grade_converter(grade):
if grade >= 90 :
return "A"
elif grade >= 80 and <= 89:
return "B"
elif grade >= 70 and <= 79:
return "C"
elif grade >= 65 and <= 69:
return "D"
else:
return "F"
# This should print an "A"      
print grade_converter(92)
# This should print a "C"
print grade_converter(70)
# This should print an "F"
print grade_converter(61)

这是我的解决方法

#  if and elif statements for calculating grade score letters
def grade_converter(grade):
if grade >= 90 :
return "A"
elif grade >= 80 and grade <= 89:
return "B"
elif grade >= 70 and grade <= 79:
return "C"
elif grade >= 65 and grade <= 69:
return "D"
else:
return "F"
# This should print an "A"      
print grade_converter(92)
# This should print a "C"
print grade_converter(70)
# This should print an "F"
print grade_converter(61)

计算机语言不是英语。人类擅长猜测复合句中重复的主语,而计算机则不然。您始终显式声明在逻辑运算符的两端测试的内容。

这是因为在表达式结构<left> and <right>中,leftright始终是独立的表达式。表达式可以基于表达式构建表达式,但计算机编程语言不会只是在right表达式中重用(部分)left表达式。

所以是的,你必须再次明确命名grade

或者,您可以使用不同的表达式形式。您可以使用链式比较表达式;Python允许您将<foo> <comparison1> <shared> and <shared> <comparison2> <bar>形式的任何表达式折叠成<foo> <comparison1> <shared> <comparison2> <bar>,并且shared表达式将只执行一次。

所以如果你转身

grade >= 80 and grade <= 89

80 <= grade and grade <= 89

您可以将其替换为

80 <= grade <= 89

但是,请注意,前面的测试已经处理了grade > 89情况,您可以安全地删除上限测试:

def grade_converter(grade):
if grade >= 90:
return "A"
elif grade >= 80:
return "B"
elif grade >= 70:
return "C"
elif grade >= 65:
return "D"
else:
return "F"

最后但并非最不重要的一点是,您可以使用计算机科学技巧。与其逐个测试每个等级带,不如使用平分法;当您的选项被排序时,这始终有效。

与其从最高值开始,不如从中间开始;这将可能性划分为2。从那里开始,您不断将可能性减半,直到您获得合适的等级带。这意味着您最多只需要对 N 种可能性进行 Log(N) 测试,而从最高等级开始最多需要 N 次测试。对于 5 个测试,差别不大(平均 1.6 步,与 5 步相比),但是当 N 变得非常大时,您很快就会注意到差异;如果您有 100 万个选项,则保证在不到 14 个步骤内找到匹配的选项。

Python 库在bisect模块中包含一个优化的实现:

import bisect
def grade_converter(grade):
grades = ['F', 'D', 'C', 'B', 'A']
limits = [65, 70, 80, 90]
return grades[bisect.bisect(limits, grade)]

正如你所指出的,你不能做类似的事情

a <= 10 and >= 20

Python无法理解该and适用于a。这是无效的语法,因为and>=都是运算符。

您可以简单地通过链式比较来做到这一点:

def grade_converter(grade):
if grade >= 90 :
return "A"
elif 80 <= grade <= 89:
return "B"
elif 70 <= grade <= 79:
return "C"
elif 65 <= grade <= 69:
return "D"
else:
return "F"

(或者在您的情况下,除法和转换)

尽管如果大声朗读,以下行听起来可能听起来可以理解为英语句子,但它根本不是正确的python语法:

elif grade >= 80 and <= 89:

原因是and是一个二元运算符,它采用两个完整的表达式,一个在左边,一个在右边。<= 89并不是一个完整的表达。

所以你的更正版本有效:

elif grade >= 80 and grade <= 89:

但实际上Python也允许以下语法:

elif 80 <= grade <= 89:

最新更新