Using isA and getA in a python way

Alex Martelli aleaxit at yahoo.com
Mon Sep 20 10:52:14 EDT 2004


Fredrik Lundh <fredrik at pythonware.com> wrote:

> "C Gillespie" wrote:
> 
> > I have long list of if statements in the form of:
> >
> > if obj.isA(): return obj.getA()
> > if obj.isB(): return obj.getB()
> > if obj.isC(): return obj.getC()
> > if obj.isD(): return obj.getD()
> > <snip>
> >
> > Is there a nicer way of doing this, perhap going through the list
> > ['A','B','C',..
> 
> well, the python way is to do:
> 
>     return obj.get()

Wonderful (as all all of the other suggestions), _if_ being an A, a B,
etc, are mutually exclusive conditions.  However, they might not be --
the OP didn't really explain his use case.  It may be that obj has the
potential to display zero or more of these characteristics at any time,
and different calling sites have different orders of priority as to
which condition they want to test first.

For example, a bar in Italy is allowed to be a milkbar (selling fresh
milk), a coffeebar (selling espresso) AND a liquorbar (selling spirits)
at the same time, but not all bars are all of these kinds.  So, I can
see myself coding, in one spot,

if bar.isMilkBar(): return bar.getMilk()
if bar.isCoffeeBar(): return bar.getCoffee('black')

but reversing these checks in other calling sites (here I've also hinted
at the possibility that the different getX methods may admit of
different signatures, which of course is a different issue).  These
naming conventions aren't the exact ones the OP specified, so let's
assume he wants to call 'isMilk' rather than 'isMilkBar' &c (weird
naming, admittedly...:-).

For this purpose, it IS indeed possible to code up 'a nicer way to do
it' as the OP asks -- either as a method of the object (possibly in a
mixin class), or as an auxiliary function, it doesn't matter all that
much in a practical sense.  /F of course knows that, but, for the OP
benefit, it could go something like...:

def preferences(obj, pref_sequence, **args_by_pref):
    for pref in pref_sequence:
        is_meth = getattr(obj, 'is'+pref, None)
        if is_meth is None: continue
        get_meth = getattr(obj, 'get'+pref, None)
        if get_meth is None: continue
        if is_meth(): return get_meth(*args_by_pref.get(pref,()))
    raise ValueError, "%r isn't any of %r" % (obj, pref_sequence)

The args_by_pref tweak is totally optional, of course, it's just what
I'd use to be able to code something like:

return preferences(bar, ('Milk', 'Coffee'), Coffee=('black',))

Also, the details of error checking &c will have to be tweaked to the
OP's content (not having the appropriate is or get method might be
considered an error, for example -- only the OP knows!).


Alex



More information about the Python-list mailing list