Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
118 views
in Technique[技术] by (71.8m points)

python - Why is calling a variable twice in a conditional statement necessary for a ranged value?

So, I solved my code issue where the one below didn't work originally ,but I would like a explanation as to why my original code didn't work as expected. If I specified the variable 'grade' once in the if/elif/else section and set the 'and' operator to the parameters I need for it to work shouldn't grade be compared against both without having to use it twice?

This is the code that didn't work

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

This was my fix

#  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)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Computer language is not English. Humans are great at guessing what subject is repeated in a compound sentence, computers are not. You always explicitly state what you are testing against on both sides of a logical operator.

That's because in the expression structure <left> and <right>, both left and right are always independent expressions. Expressions can build on expressions on expressions, but a computer programming language will not just re-use (a part of) the left expression in the right expression.

So yes, you have to explicitly name grade again.

Or you could use a different expression form. You could use a chained comparison expression; Python lets you collapse any expression of the form <foo> <comparison1> <shared> and <shared> <comparison2> <bar> into <foo> <comparison1> <shared> <comparison2> <bar>, and the shared expression will be executed just once.

So if you turned

grade >= 80 and grade <= 89

into

80 <= grade and grade <= 89

you can replace that with

80 <= grade <= 89

However, note that the preceding test already handled the grade > 89 case, you can safely drop the upper bound tests:

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"

Last but not least, you can use a Computer Science trick. Rather than test each grade band separately, one by one, you could use bisection; this always works when your options are sorted.

Instead of starting at the highest value, start in the middle; that divides the possibilities in 2. From there, you keep halving the possibilities until you have the right grade band. This means you only have to do, at most, Log(N) tests for N possibilities, while starting at the top grade will require up to N tests. For 5 tests that's not much of a difference (1.6 steps on average, vs 5), but when N becomes really large, then you'll quickly notice a difference; if you had 1 million options, you could find the matching option in less than 14 steps, guaranteed.

The Python library includes an optimised implementation in the bisect module:

import bisect

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...