[Tutor] Case acceptance using raw_input

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Wed Feb 16 01:26:14 CET 2005



On Wed, 16 Feb 2005, Tony Meyer wrote:

> >> Is there a better way for raw_input to accept both caps and
> >> lower case letters than:
> [...]
> >>    if action == 'y' or action == 'Y':
> >
> > if action in 'yY':
> > dostuff()
> [...]
> > Although, that does mean that if a user enters 'nN' they'll
> > get no, but that shouldn't be a huge problem, and it it does,
> > you can just do a if len(action) != 1...


Hello!

There's one other major problem that's not obvious: watch what happens if
the user just presses Enter:

###
>>> if raw_input("y/n?") in "yY":
...     print "Yes!"
...
y/n?
Yes!
###

The empty string "" is a substring of everything.  *grin* So the length
check against the input is something we definitely need to do if we take
this approach.


Given that, it's probably safer to go with Tony's:

>     if action.lower() == 'y':

and if we end up doing a lot of yes/no questions to the user, it'll
probably be a good idea to write a helper function or two to do the grunt
work of parsing the user's input:

###
def isYes(choice):
    return choice.lower() == 'y'

def isNo(choice):
    return choice.lower() == 'n'
###

just so that we don't have to worry about the problem anymore.




I see that the original code is written using a tail-call recursion style,
such as one supported by Scheme.  Here's the code, with isYes()/isNo()
modifications:

###
def aFunction():
   action = raw_input("Perform an action?(y,n): ")
   if isYes(action):
       anotherFunction()
   elif isNo(action):
       yetAnotherFunction()
   else:
       aFunction()
###

Unfortunately, Python doesn't support tail call optimization.  *sigh* This
means that the recursion here takes stack space in Python.


To get around Python's lack of tail-call optimization, you may want to use
an explicit loop here instead:

###
def aFunction():
    while True:
        action = raw_input("Perform an action?(y,n): ")
        if isYes(action):
            anotherFunction()
            break
        elif isNo(action):
            yetAnotherFunction()
            break
###


If you have more questions, please feel free to ask!




More information about the Tutor mailing list