0

I have a simple program that converts numerical scores into letter grades, but the condition score_int >=0 and score_int <= 100 isn't working. It lets me put values < 0 and > 100 and not display error message 'Enter a valid number'. How come?

while True :
    score_str = input('Enter your numerical score:')
    try:
        score_int = int(score_str)
        score_int >= 0 and score_int <= 100 # this condition isn't working for some reason**
    except:
        print('Enter a valid number')
        continue

    if score_int >= 90 and score_int <= 100 :
        print('A')
        continue
    elif score_int >= 80 and score_int < 90 :
        print('B')
        continue
    elif score_int >= 70 and score_int < 80 :
        print('C')
        continue
    elif score_int >= 60 and score_int <= 70 :
        print('D')
        continue
    elif score_int <= 60 :
        print('F')
        continue

Expected the code to display error message for values <0 and >100

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
Rambo
  • 1
  • 1
  • 1
    Please [edit] your question to fix your indentation. What do you expect the line `score_int >= 0 and score_int <= 100` to do? That just evaluates to a boolean and then discards the results. – Brian61354270 Feb 16 '23 at 17:54
  • I'm probably not using it correctly, but I thought that score_int >= 0 and score_int <= 100 would return False and end the code, but it's not – Rambo Feb 16 '23 at 17:55
  • 2
    The line `score_int >= 0 and score_int <= 100` is not a conditional statement; it is just a declaration which will either result in `True` or `False`, but you are not doing anything with that value. You are not using `assert` or `if`. It is equivalent to just putting `True` or `False` on its own line, or calling a function that returns a value but not saving the returned value. It will not raise an exception unless you use `assert`. But raising and catching exceptions when you could instead just use a simple `if` statement doesn't make sense to me. – Random Davis Feb 16 '23 at 17:56
  • As an aside, you don't need those `continue` statements. The clauses will automatically resume execution after the if/elif/else suite completes and that will take you back to the top of the loop. – tdelaney Feb 16 '23 at 18:38

3 Answers3

1

To raise an exception if your expression is not True, you could use the assert keyword:

assert score_int >= 0 and score_int <= 100

If the expression with assert is False it will raise AssertionException.

Also, you should avoid a bare except clause. See What is wrong with using a bare 'except'? Instead, specify the exceptions you expect the code inside the try block to raise. In this case, your code can raise a ValueError (if score_str is an invalid integer, or an AssertionError if the assert above fails.

Your code would be:

while True:
  score_str = input('Enter your numerical score:')
  try:
      score_int = int(score_str)
      assert score_int >= 0 and score_int <= 100
  except (ValueError, AssertionError):
      print('Enter a valid number')
      continue

  if score_int >= 90 and score_int <= 100 :
      print('A')
  elif score_int >= 80 and score_int < 90 :
      print('B')
  elif score_int >= 70 and score_int < 80 :
      print('C')
  elif score_int >= 60 and score_int <= 70 :
      print('D')
  elif score_int <= 60 :
      print('F')

I also removed the unnecessary continue inside the conditions, since they are elif conditions and there is nothing in the loop after that if..elif block

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
palvarez
  • 1,508
  • 2
  • 8
  • 18
  • 1
    You should _specifically_ catch `ValueError` and `AssertionError`. Bare except clauses are [bad.](https://stackoverflow.com/questions/54948548/what-is-wrong-with-using-a-bare-except) I edited your answer to include this – Pranav Hosangadi Feb 16 '23 at 18:54
1

When you run this expression score_int >= 0 and score_int <= 100 you are not doing anything with its value. Try blocks only fail if an exception is raised, not if something is true or false. That's what if statements are for.

You have to use your expression in the condition of an if statement.

So the way I went about it was to invert the condition you wrote so that if the user gives a number lower than zero or a number greater than a hundred, we ask them to input a number between 0 and 100.

I also removed all the continue statements since they are not necessary, but you can leave them if you prefer.

while True:
    score_str = input('Enter your numerical score:')
    try:
        score_int = int(score_str)
    except ValueError:
        print('Enter a valid number')

    if score_int <= 0 or score_int >= 100:
        print("Enter number between 0 and 100")
    elif score_int >= 90 and score_int <= 100:
        print('A')
    elif score_int >= 80 and score_int < 90:
        print('B')
    elif score_int >= 70 and score_int < 80:
        print('C')
    elif score_int >= 60 and score_int <= 70:
        print('D')
    elif score_int <= 60:
        print('F')
  • 1
    I edited your code to _specifically_ catch `ValueError`. Bare except clauses are [bad.](https://stackoverflow.com/questions/54948548/what-is-wrong-with-using-a-bare-except) – Pranav Hosangadi Feb 16 '23 at 19:02
0

Consider the case where not of the if/elif conditions pass. What are you left with? The cases where the score falls outside your expected values. So you can just add an else to catch these cases. Also, you don't need all the continue statements since the loop will continue anyway. Here's one way to do this:

while True :
    score_str = input('Enter your numerical score:')
    try:
        score_int = int(score_str)
    except ValueError:
        print('Enter a valid number')
        continue
    if 90  <= score_int <= 100:
        print('A')
    elif 80 <=  score_int < 90:
        print('B')
    elif 70 <=  score_int < 80:
        print('C')
    elif 60 <= score_int <= 70:
        print('D')
    elif 0 <= score_int <= 60:
        print('F')
    else:
        print('Enter a valid number')

This also lets you put the minimal amount of code in the try block which is helpful on larger projects for debugging and lets you catch the specific error you are anticipating.

For a succinct way of doing the score to grade mapping take a look at the first example in the bisect module.

Mark
  • 90,562
  • 7
  • 108
  • 148