Best way to make a number of tests against an object('s attributes) with absence of switch statement?
Bruno Desthuilliers
bruno.42.desthuilliers at websiteburo.invalid
Mon Jun 16 05:06:58 EDT 2008
Phillip B Oldham a écrit :
> What would be the optimal/pythonic way to subject an object to a
> number of tests (based on the object's attributes) and redirect
> program flow?
>
> Say I had the following:
>
> pets[0] = {'name': 'fluffy', 'species': 'cat', 'size': 'small'}
> pets[1] = {'name': 'bruno', 'species': 'snake', 'size': 'small'}
> pets[2] = {'name': 'rex', 'species': 'dog', 'size': 'large'}
>
> What I'd like to do is loop through 'pets', and test each object. Some
> of the tests I'd like to perform are:
>
> Is the size 'small' and species not 'dog'?
> Is the species 'cat' and name 'fluffy'?
> Is the species not 'dog' or 'cat'?
>
> In PHP I'd use a switch statement similar to the following:
>
> foreach( $pets as $pet) {
> switch(true) {
> case ( $pet['size'] === 'small' && $pet['species'] !== 'dog' ):
> // do something
> break;
> // etc...
> }
> }
>
> Now, I understand from a bit of googling that python doesn't have a
> switch statement, and because of this people rely on python's
> polymorphism.
You could also put it the other way round : Python doesn't have a switch
statement because peoples use polymorphism !-)
(nb : not that my "reversed" statement is in any way more true than
yours - but the fact is that procedural switch statement vs OO
polymorphic dispatch is not such a new topic...)
> Thats great, but I've yet to come across a decent
> example which make a "click".
>
> Any thoughts on how to proceed?
The braindead canonical OO solution would be to make a specific class
for each species each implementing it's own version of do_something().
The problem is that it would only dispatch on species, not other
attributes (size etc). Which is a inherent limitation of the canonical
OO type-based single dispatch mechanism.
A more elaborate canonical OO solution would be to use the visitor
pattern to overcome the single dispatch limitation.
A yet more elaborate (but way less canonical) solution is to use
predicate-based dispatch (cf Philip Eby's work).
Anyway, and while each dispatch mechanism (from basic branching to
complex predicate-based systems) has it's pros and cons, I'd first think
twice (or more) about whether my current dispatch problem has some
relative stability wrt/ the domain - IOW, it's structurally part of the
domain and won't change anytime soon - or if it's one of those ad-hoc
short-lived illogical "business rule" that is potentially subject to
unpredictable change any other day. Because the appropriate solution
really depends on this kind of considerations.
Now wrt/ your concrete example: truth is that, while expressed as a
switch statement, it's in fact really a if/elif/.../, since the
condition is not a constant (so you don't gain any performance gain from
using a switch). So the simplest translation in Python is to use an
if/elif/...
for pet in pets:
if pet['size'] == 'small' and pet['species'] !== 'dog':
// do something
elif (other complex condition):
// etc
More information about the Python-list
mailing list