On Dec 9, 5:39 pm, Steven D'Aprano <ste...@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...@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. -- http://mail.python.org/mailman/listinfo/python-list