Using isA and getA in a python way

C

C Gillespie

Dear All,

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',..

Many thanks

Colin
 
F

Fredrik Lundh

C Gillespie said:
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()

if that's too much work, you could add some kind of identifier
to each obj class, and do:

return getattr(obj, "get" + obj.tag)()

if that's too much work, you could create a map, mapping class names
(or class objects) to tags, and do:

return getattr(obj, "get" + my_lookup_table[obj.__name__])

etc.

</F>
 
A

Alex Martelli

Fredrik Lundh said:
C Gillespie said:
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
 
A

Andrew Dalke

C said:
if obj.isA(): return obj.getA()
if obj.isB(): return obj.getB() ...
Is there a nicer way of doing this, perhap going through the list
['A','B','C',..

(Warning: Untested code. Should be enough to
lead you to the right documentation if it doesn't work)


for name in ['A', 'B', 'C']:
if getattr(obj, 'is' + name)():
return getattr(obj, 'get' + name)()

Andrew
(e-mail address removed)
 
J

Jeremy Bowers

Dear All,

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>

This represents some concept in your mind. You don't tell us what it is,
but for example your concept might be "serialize":

if obj.isA(): return obj.serializeAsA()
if obj.isB(): return obj.serializeAsB()

Or any number of other things.
Is there a nicer way of doing this, perhap going through the list
['A','B','C',..

For each of those obj types, assuming you control the class (which seems
likely), add a method that represents the *concept* you have in your head,
using that concept to name the method. This may take practice, and there
are a number of "code smells" (Google the term) that are associated with
this; the biggest one is that the harder it is to give the concept a name,
the more likely it is that your design needs more thinking. (This is not
an absolute.) Then, your sequence boils down to

obj.get()

or in my example,

obj.serialize()

Note that this new method is *in addition to* your current methods; "getA"
means something, and this new method on the class means something else,
even if it happens to be implemented in the same way and consist of
"return self.getA()" for the A object.

If you give more details, people may be able to provide more specific help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top