Need help improving number guessing game

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Tue Dec 16 04:26:55 EST 2008


feba a écrit :
>> .strip() returns a copy of the string without leading and ending
> whitespaces (inlcuding newlines, tabs etc).
> 
> Ahh. I had removed it because it didn't seem to do anything, but I've
> readded it.
> 
> And I understand your dictionary stuff correctly now, I think, and I
> worked it in. Currently, I have:
> 
> 
> import random
> 
> def safeint(prompt="y"):
>     while True:
>         x = input(prompt)
>         try:
>             x = int(x)
>         except ValueError:
>             print("BAD INPUT!")
>         else:
>             break
>     return x
> 
> def safestr(prompt="y"):
>     while True:
>         x = input(prompt)
>         try:
>             x = str(x)

Doesn't input already return a string ?

>         except ValueError:
>             print("BAD INPUT!")
>         else:
>             break
>     return x

You could as well replace the 'break' statement by 'return x' - since
returning will obviously break the loop


Now don't you notice kind of a pattern in these two functions ? 
obviously, the only thing that change is the conversion/validation part. 
The good news is that Python functions are objects too, so you can pass 
them as params to another function. The generic version of your above 
code could be:


def safeinput(prompt, convert):
      while True:
          x = input(prompt)
          try:
              x = convert(x)
          except ValueError, e:
              print("Bad input : %s" % e)
          else:
              return x


then you can use it for int:

i = safeinput("Please enter an integer", int)

or use more complex conversion/validation:

def yesno(s):
    s = s.strip().lower()
    if not s in ("y", "n"):
        raise ValueError("please answer with 'y' or 'n'")
    # we return a boolean
    return s == 'y'

answer = safeinput("really do this ?", yesno)


Last point : if your conversion/validation function needs more arguments 
than the value to convert - ie : converting to an int and vaidating this 
int is in a specified range, which require mini and maxi arguments for 
the range - you can use partial evaluation[1]:

from functools import partial

def int_in_range(x, mini, maxi):
    x = int(x)
    if not mini <= x <= maxi:
        raise ValueError("%s is not in range (%s, %s)" % (x, mini, maxi))
    return x

i = safeinput(
         "Please enter an int between 1 and 99",
         partial(int_in_range, mini=1, maxi=99)
         )


[1] given the function f(x, y): return x + y, the partial evaluation 
partial(f, x=2) is a function fx(y) that when called returns the result 
of f(2, y).


(snip)

>> rewrite it once again using objects instead of dicts ?
> 
> I'd need to find out how those work,

Mostly as glorified dicts with associated functions. Your game and 
players dicts are obvious candidates. Whenever you see a dict with a 
more or less defined "structure" and a set of functions working on this 
dict, you have in fact a class waiting to be born.


> and I have a list of python stuff
> to read piling up anyway... That said, I think for something like
> that, something that's not a major flaw, I'd prefer to make something
> else, and maybe work on this again later on. There is only so much
> guessing numbers one person can take.

Indeed. That was just a suggestion, and it would have been pretty 
interesting IMHO as a basis for a "from Q&D procedural scripting to OO 
application programing" tutorial.



More information about the Python-list mailing list