Implicit lists

Mel Wilson mwilson at the-wire.com
Fri Jan 31 16:38:08 CET 2003


In article <XOq_9.48875$Hl6.6191395 at news010.worldonline.dk>,
Max M <maxm at mxm.dk> wrote:
>Very often you want a function that has this interface:
>
>     def getWhere(options): # options is a list
>         "generates query"
>
>it could generate a query like:
>
>     SELECT * FROM table WHERE option='spam' or option='ni'
>
>So the easiest way to do this is to write a function like this:
>
>     def getWhere(options):
>         return 'SELECT * FROM table WHERE %s' % ' or '.join(
>                ['option=%s' for opt in options])
>
>But frequently you will only call getWhere() with one argument. So
>instead of having to call it like:
>
>     def getWhere(['spam']):
>         "generates query"
>
>You want to call it like
>
>     def getWhere('spam'):
>         "generates query"

   Then there is the possibility for confusion.  This
Do-What-I-Mean feature has already injected lumps into base
Python:


Python 2.1.3 (#35, Apr  8 2002, 17:47:50) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> print 1
1
>>> print (1,2)
(1, 2)
>>> print '%s' % 1
1
>>> print '%s' % (1,2)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: not all arguments converted
>>>

by giving a possibly unwanted, or unwonted, meaning to
tuples vs. other types in doing string modulus.  (Strictly,
the unwonted meaning is being given to the other types, by
relaxing the requirement that '%' take a tuple.  Either way
though, forget what you're doing and KABOOM!)

   I hit a similar thing with a wxTreeCtrl method.  There is
a method that creates a tree item and optionally associates
a data instance of the programmer's choosing with the item.
I chose a triple containing some database keys and the
method screamed back that it was made to be called with 3
arguments, and I was calling it with 5. I guess there's a
*arg in there somewhere.

   The container/contents distnction is not going to be
swept aside anytime soon.  If you hand me a box of raisins,
do you want price tags on the box or on the raisins?  How
about a box of soup cans?  A box of apples?


>If you do not have polymorphic interfaces you will need to typecheck
>your argument everytime you call the function:
>
>if type(options) == type(''): # I *know* this sucks!
>     getWhere([options])
>else:
>     getWhere(options)
>
>If you want to make 2 functions:
>
>     def getWhereByOne('spam'):
>         "generates query"
>
>     def getWhere(['spam']):
>         "generates query"
>
>You will need to check if the argument is a list or a string in all the
>code wich calls one of the function.

   The closer you are to the source of the data, the better
chance that you will know the form it's in.  If the caller
has forgotten the form then the callee's chances are even
worse.  It's best that the input validation code line things
up right at the start, for example:

        line = infile.readline().strip()
        try:
            query_args = line.split()
        except ValueError:
            query_args = [line]

and from now on, we call

        result = GetWhere (query_args)

with a clear conscience, at least as far as the type of
query_args is concerned.

   I'm actually living this problem now.  I started out on a
wxPython app.  Since I didn't know wxPython, or much of
Windows, I relaxed my design methods; I was 'exploring'.
Now I have a thousand lines of coded coincidences that
produce a result that isn't obviously wrong, and I have to
carve them into a program.  (not complaining..  I call this
'tuition fees'.)

        Regards.        Mel.




More information about the Python-list mailing list