[Tutor] Most pythonic input validation
cwitts at compuscan.co.za
Fri Oct 16 12:20:51 CEST 2009
>> Message: 3
>> Date: Thu, 15 Oct 2009 16:50:57 +0100
>> From: Rich Lovely <roadierich at googlemail.com>
>> To: Wayne Werner <waynejwerner at gmail.com>
>> Cc: "tutor at python.org" <Tutor at python.org>
>> Subject: Re: [Tutor] Most pythonic input validation
>> <f0b4202b0910150850w7fe680c0v400bc5d432f716b at mail.gmail.com>
>> Content-Type: text/plain; charset=windows-1252
>> 2009/10/15 Wayne Werner <waynejwerner at gmail.com>:
>>> I'm writing a text based menu and want to validate the user input. I'm
>>> giving the options as integers, and I want to make sure the user
>>> enters a
>>> proper value.
>>> Here's what I've got so far:?http://pastebin.com/m1fdd5863
>>> I'm most interested in this segment:
>>> ?? ?while True:
>>> ?? ? ? ?choice = raw_input(prompt)
>>> ?? ? ? ?if valid_choice(choice, 0, len(options)-1):
>>> ?? ? ? ? ? ?break
>>> ?? ?return choice
>>> Is that the most pythonic way of validating? Is there a better way?
>>> As an aside, in the valid_choice function I know I could do:
>>> if not choice in range(min, max)
>>> but I figured a comparison would probably be the better choice,
>>> To be considered stupid and to be told so is more painful than being
>>> gluttonous, mendacious, violent, lascivious, lazy, cowardly: every
>>> every vice, has found its defenders, its rhetoric, its ennoblement and
>>> exaltation, but stupidity hasn?t. - Primo Levi
>>> Tutor maillist ?- ?Tutor at python.org
>>> To unsubscribe or change subscription options:
>> The most pythonic way would be to use a try except block:
>> while True:
>> choice = raw_input(prompt)
>> except (KeyError, IndexError, TypeError):
>> print "Invalid input, try again."
>> return choice
>> Also, did you want to convert choice to an int at some point? You
>> appear to be comparing it to a number in valid_choice(), but it will
>> be passed out of the method as a str.
>> Hence I've added a conversion to int, and I'm catching KeyError (for
>> dicts), IndexError (for lists), and TypeError, for when int(choice)
>> This is a principle called "It's Easier to Ask Forgiveness than
>> Permission" (EAFP), which is one of the pythonic principles.
>> Hope that helps.
>> Rich "Roadie Rich" Lovely
> As I am a new programmer I am specifically trying to pay attention to
> when you guys discuss making thing more python like.
> I am a bit confused though on a couple things in this code. Probably
> since I have not dealt with it as of yet.
> The first is the while statement. I have made a successful menu
> selection but my while statement is:
> while prompt != 0:
> 0 of course meaning exit. Does "while True:" mean the same?
> Second is the input statement. Could you not just put choice =
> int(raw_input(prompt)) instead of using two different statements? Or
> is it that my example will return as string?
> The third is the "try" statement. How is this different from the
> "for" loop or "if" loop?
> The fourth is except (KeyError, IndexError, TypeError): why do you
> check for three different types of errors?
> Thanks in advance,
> Tutor maillist - Tutor at python.org
> To unsubscribe or change subscription options:
1) `while True` will result in an infinite loop unless you test for your
prompt condition inside the loop and if it's true then use a break
statement to exit the loop, eg.
if prompt == 0:
2) If you were to put the `choice = int(raw_input(prompt))` into one
line, remember to put it in a try/except block as you could be casting
an alphanumeric into an integer. The reasoning behind putting it on two
lines is to increase readability and so that you have a variable
`choice` which contains the actual input in case you wanted to use it
for something if it causes an exception, eg.
choice = raw_input(prompt)
except (KeyError, IndexError, TypeError):
print '%s is not a valid choice' % choice
3) If you start a `try` block it is because you want to handle any
errors occurring from the statements / expressions in the block itself.
It is not a loop, it just runs through once completely or until it
receives the first exception and in that case then moves onto the
4) The three exceptions lists are for various errors that might have
The KeyError is if `options` is a dictionary and the key (contained in
choice) is not in your dictionary, although for a dictionary I would
rather write `if int(choice) in options:`.
The IndexError is if `options` is a list and your choice was supposed to
be the index that you want to seek to, eg.
options = ['Exit', 'Start New Game', 'High Scores']
choice = raw_input(prompt) # lets say you use the number 3 here
print 'Selection out of range, please use a number between 0 and %s'
Counting starts from zero so there are 0, 1, 2 as valid choices in this
The TypeError, should be a ValueError, is for catching conversion
errors. If you supply a choice of 'a' and try and convert that to an
integer it will throw a ValueError letting you know that what you are
trying to convert is not an integer. TypeError will catch a NoneType
conversion which you won't be able to type in on the console.
Hope that helps.
More information about the Tutor