switch

Asun Friere afriere at yahoo.co.uk
Wed Dec 9 19:45:42 EST 2009


On Dec 9, 5:39 pm, Steven D'Aprano
<ste... at REMOVE.THIS.cybersource.com.au> wrote:
> On Tue, 08 Dec 2009 21:36:23 -0800, Asun Friere wrote:
> > On Dec 9, 4:02 pm, Kee Nethery <k... at kagi.com> wrote:
> >> I string together a bunch of elif statements to simulate a switch
>
> >> if foo == True:
> >>         blah
> >> elif bar == True:
> >>         blah blah
> >> elif bar == False:
> >>         blarg
> >> elif ....
>
> > This code is probably symptomatic of poor design. (Not to mention that
> > your condition tests).  For which reason python has no 'case' statement
> > and why no decent OO language should.
>
> That's a provocative statement.
>

My reply was lost in the aether, so here goes again.

If it's provocative, it is at least hedged.  It is merely symptomatic
and only probably so, because there are numerous instances where case
logic is the only sensible solution.  I'm not advocating some cargo-
cult rule for the elimination of all uses of elif.  If I were I would
rightly be presented with numerous code examples where a switch is a
sensible option, much as happens when someone pronounces against the
humble goto statement.


> > It is a principle of OO design that "an object should know what to do
> > itself."  Rather running an object though a series of tests, it is
> > better to send the object a message, relying on polymorphism or duck-
> > typing, and deal with any exceptions thrown.
>
> Perhaps that's true, but you'll note that the example given above doesn't
> run a single object through a series of tests, but runs a series of tests
> on DIFFERENT objects, to find the first which matches.
>

Well actually two objects with one being tested twice.  But you are
right, I was being sloppy when I wrote "running an object" especially
in light of the fact that the following clause makes more sense when
run against objects of potentially different class.  Same for dispatch
mechanisms of course.

What I'm saying is that when you find a large if/elif/else in your
code, regard it with suspicion and "consider" whether better design
might not eliminate it.  And I'm speaking as someone who still has to
maintain some code (in perl not python) which has an if/elif/else
statement spanning 5 A4 pages.  What's worse, I was the one who did
this to myself some 8 years ago.

What I'm also saying is "learn about dispatch mechanisms," they are
about the most useful patterns out there (next to the State pattern).
As a matter of practice I have found that more often than not, large
case statements can better be solved using double-dispatch.  Obviously
not all.  Obviously!

> But putting that aside, I find myself wondering how you would deal with
> the following switch-like series of tests.
>
> def print_grades(score):
>     if not 0 <= score <= 100:
>         raise ValueError("score must be between 0 and 100")
>     if score < 50:
>         print "You have failed."
>         consider_suspension()
>     elif score == 50:
>         print "You have just passed by the skin of your teeth."
>     elif score < 60:
>         print "You have scored a D. You need to try harder."
>     elif score < 70:
>         print "You have scored a C."
>     elif score < 80:
>         print "You have scored a B. Well done."
>     elif score < 100:
>         print "Congratulations, you have scored an A."
>     else:
>         assert score == 100
>         print "You have scored a PERFECT 100% SCORE!!!"
>         if not evidence_of_cheating():
>             call_newspapers()
>
> Obviously that could, with a non-trivial amount of work, be turned into a
> dictionary dispatch, but is the benefit worth the extra effort?
>

Probably not.  Depending on the nature of the app, I'd probably be
calling score.print_grades() and using cutoff values of 85, 75, 60 and
50 (perhaps not even hardcoded into the logic), but sure this is a
fine example of a place where a solution other than a simple switch
would be overkill.  As such this example would be a good counter to
the absolute repudiation of case logic I did not make.  I doubt,
however, that it is of great pedagogic value in alerting programmers
to the design options available to them in overcomming what the
perceive as a lack in the language.



More information about the Python-list mailing list