2

Here's my code:

total = int(input("How many students are there "))
print("Please enter their scores, between 1 - 100")

myList = []
for i in range (total):
    n = int(input("Enter a test score >> "))

    myList.append(n)

Basically I'm writing a program to calculate test scores but first the user has to enter the scores which are between 0 - 100.

If the user enters a test score out of that range, I want the program to tell the user to rewrite that number. I don't want the program to just end with a error. How can I do that?

Mel
  • 5,837
  • 10
  • 37
  • 42
Average kid
  • 6,885
  • 6
  • 21
  • 17
  • 1
    Create a helper function that loops forever, calling `input()` on every loop. When a correct value is input, return it, otherwise print an error and let the loop ask again. – millimoose Dec 17 '12 at 20:35
  • Nobody wants to check that the input is a number? – f p Dec 17 '12 at 20:50
  • 1
    @fp: That's not part of the specification. But it's pretty easy to add, of course. – abarnert Dec 17 '12 at 20:51

3 Answers3

10
while True:
   n = int(input("enter a number between 0 and 100: "))
   if 0 <= n <= 100:
      break
   print('try again')

Just like the code in your question, this will work both in Python 2.x and 3.x.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • He doesn't have to say which he's using; the fact that he's doing `int(input` pretty much proves it's Py3. – abarnert Dec 17 '12 at 20:47
  • @abarnert: It *hints* at it, but doesn't prove anything. I only write Python 2.x, yet routinely use parentheses with `print()`. I'd also write `int(input(...))` here, just to make the code future-proof. – NPE Dec 17 '12 at 20:49
  • With all due respect, someone who's clearly a beginner is not being taught to write Python 2 code that usually also works in Python 3; he's being taught to write Python 3 code. – abarnert Dec 17 '12 at 20:51
  • 2
    @abarnert: I think we are debating a trivial, irrelevant issue. I therefore propose that we leave it at that. – NPE Dec 17 '12 at 20:52
5

First, you have to know how to check whether a value is in a range. That's easy:

if n in range(0, 101):

Almost a direct translation from English. (This is only a good solution for Python 3.0 or later, but you're clearly using Python 3.)

Next, if you want to make them keep trying until they enter something valid, just do it in a loop:

for i in range(total):
    while True:
        n = int(input("Enter a test score >> "))
        if n in range(0, 101):
            break
    myList.append(n)

Again, almost a direct translation from English.

But it might be much clearer if you break this out into a separate function:

def getTestScore():
    while True:
        n = int(input("Enter a test score >> "))
        if n in range(0, 101):
            return n

for i in range(total):
    n = getTestScore()
    myList.append(n)

As f p points out, the program will still "just end with a error" if they type something that isn't an integer, such as "A+". Handling that is a bit trickier. The int function will raise a ValueError if you give it a string that isn't a valid representation of an integer. So:

def getTestScore():
    while True:
        try:
            n = int(input("Enter a test score >> "))
        except ValueError:
            pass
        else:
            if n in range(0, 101):
                return n
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • What if the range were from 0 to 1,000,000? Would you compare `n` to every number in that range? – NPE Dec 17 '12 at 20:37
  • @NPE: Why would you do that? Just `n in range(0, 1000001)`. (In Python 2, you'd want `xrange` instead of `range`, of course.) Do you not understand basic Python? – abarnert Dec 17 '12 at 20:38
  • @abarnert NPE was talking about performance issues with range. Using ``0 <= n <= 1000000`` is a hell of a lot quicker. – Markus Unterwaditzer Dec 17 '12 at 20:40
  • 2
    @NPE As of Python 3, `range` is a generator-like type that defines a custom `__contains__()`. It's not a stretch to assume that method is implemented sanely. – millimoose Dec 17 '12 at 20:40
  • @MarkusUnterwaditzer The point is that the Python 3.x `range()`, and (maybe) the Python 2.x `xrange()` might not have the imagined performance issues. (Not sure about the latter because `xrange()` doesn't have a `__contains__()` method.) – millimoose Dec 17 '12 at 20:41
  • 1
    @MarkusUnterwaditzer: And the OP is clearly using Python 3, given the `print` function and the use of `input` (instead of `raw_input`) returning a string. – abarnert Dec 17 '12 at 20:43
  • 3
    @millimoose: In Python 2.7.3, `xrange()` does have the imagined performance issues. `n in xrange(...)` iterates over the values. – NPE Dec 17 '12 at 20:43
  • Right. `2**30 in xrange(2**31)` on Python 2.x takes forever, while under 3.x, `2**30 in range(2**31)` returns immediately. So this is only a good approach under Python 3.x – millimoose Dec 17 '12 at 20:45
  • @millimoose: I added the Python 3 note to the answer. But the OP is clearly using Python 3, and is a beginner, so he likely doesn't care about Python 2 any more than he cares about Ruby or Haskell. – abarnert Dec 17 '12 at 20:46
0

You can use a helper function like:

def input_number(min, max):
    while True:
        n = input("Please enter a number between {} and {}:".format(min, max))
        n = int(n)
        if (min <= n <= max):
            return n
        else:
            print("Bzzt! Wrong.")
millimoose
  • 39,073
  • 9
  • 82
  • 134