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
--
http://mail.python.org/mailman/listinfo/python-list