By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,612 Members | 1,632 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,612 IT Pros & Developers. It's quick & easy.

Best way to make a number of tests against an object('s attributes)with absence of switch statement?

P: n/a
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. Thats great, but I've yet to come across a decent
example which make a "click".

Any thoughts on how to proceed?
Jun 27 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a
On Jun 14, 12:25 pm, Phillip B Oldham <phillip.old...@gmail.com>
wrote:
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'}
I'd suggest that you have a Pet class, instead of using dicts.
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. Thats great, but I've yet to come across a decent
example which make a "click".

Any thoughts on how to proceed?
A switch statement is "optimal" when a variable needs to be tested
against N known constant values ... a compiler can emit code that
takes O(1) time (or O(log(N)) if the constants are sparse) instead of
O(N).

However the way you are using switch, it can't be other than O(N) and
it is just syntactic lemon juice for not having (or not using) if ...
elif ... else.

Python version:

for pet in pets:
if pet.size == 'small' and pet.species != 'dog':
pet.feed() # class instances can have user-definable methods
# don't need "break" to escape from if statement
elif ..... etc ...

HTH,
John
Jun 27 '08 #2

P: n/a
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

Jun 27 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.