-1

I've been working my way through the Python for Everybody book by Charles Severance. I'm stuck on one of the problems, even a worked example online doesn't seem to fully answer the question.

Exercise 7: Rewrite the grade program from the previous chapter using a function called computegrade that takes a score as its parameter and returns a grade as a string.


Score

>= 0.9 A
>= 0.8 B
>= 0.7 C
>= 0.6 D
<0.6 F



Enter score: 0.95

A

Enter score: perfect

Bad score

Enter score: 10.0

Bad score

Enter score: 0.75

C

Enter score: 0.5

F

Run the program repeatedly to test the various different values for input.

My code is:

def computegrade(score):
    if float(score)>1:
        return 'Bad score'
    elif float(score)>=0.9:
        return 'A'
    elif float(score)>=0.8:
        return 'B'
    elif float(score)>=0.7:
        return 'C'
    elif float(score)>=0.6:
        return 'D'
    elif float(score)<0.6:
        return 'F'
    else:
        return 'Bad score'

...which seems to work until I type in "perfect" or any kind of non-numerical input (throws an error). Just wondering why this doesn't work with my else statement, when word inputs don't fit other criteria?

martineau
  • 119,623
  • 25
  • 170
  • 301
Diego
  • 7
  • 1
  • 1
    The else is never reached, because the comparison *can't be made* if the input isn't numerical. An error is totally different to the comparison just not being true, read e.g. https://docs.python.org/3/tutorial/errors.html. – jonrsharpe Dec 13 '20 at 08:54
  • _Use_ that fact that an exception is being raised to detect that something invalid (i.e. non-numerical) has been entered and handle it as desired (via a `try`/`except`). – martineau Dec 13 '20 at 09:14

2 Answers2

0

Like most programming language, if..elif...else in python works sequentially, meaning from your function, the line if float(score)>1: is executed. Now, once you see the full error you will see that python has pointed you to this line as the error. In this line, it is trying to convert any non-numeric input into a floating point number, which it cannot. Thus your error.

If you want to fix these kinds of issues you have to use exception handling. Meaning, you want to avoid your program to crash when you are not getting required data type. For which try...catch comes in handy, as explained here - exception handling, and as some other answers have suggested. Also, there are many other methods, like switch case, type checking etc.

Note:

  • considering OP I am putting links for some methods I explained which might be helpful for others too.
  • type checking might always not be a good idea, but yes you can solve this problem with type checking if score.isnumeric() but this works for only integer value, not float.
Mr. Hobo
  • 530
  • 1
  • 7
  • 22
  • How would type hinting or checking help here? – jonrsharpe Dec 13 '20 at 09:03
  • _type hinting_: My point of view, someone who wants to interact with the function should at least be aware what the function is expecting as input? _type checking_: directly print if the input is wrong, or send statement from the else block? – Mr. Hobo Dec 13 '20 at 09:07
  • For this kind of problem, switch-case can also be used. But, I don't think OP is looking for these solutions, right? – Mr. Hobo Dec 13 '20 at 09:08
  • 1
    Well if I said it was `def computegrade(score: str) -> str:` would it be clearer why *type* checks aren't going to be helpful? – jonrsharpe Dec 13 '20 at 09:08
  • And Python doesn't have a switch case, so no. – jonrsharpe Dec 13 '20 at 09:09
  • No, not present directly. But can be implemented [like this](https://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python) – Mr. Hobo Dec 13 '20 at 09:10
  • Got your point on type hinting! I will make the necessary changes. @jonrsharpe – Mr. Hobo Dec 13 '20 at 09:11
  • You can use a dictionary to approximate a switch, but how would you do that with floats? – jonrsharpe Dec 13 '20 at 09:12
  • depends on the use case. like here, you can bin the data into class and apply switch-case. – Mr. Hobo Dec 13 '20 at 09:29
0
def computegrade(score):
    try:
        score = float(score)
    except ValueError:
        return 'Bad Score'
            
    if score > 1:
        return 'Bad score'
    elif score >= 0.9:
        return 'A'
    elif score >= 0.8:
        return 'B'
    elif score >= 0.7:
        return 'C'
    elif score >= 0.6:
        return 'D'
    elif score < 0.6:
        return 'F'

a = computegrade(input())
print(a)
Henry Tjhia
  • 742
  • 1
  • 5
  • 11