views:

5149

answers:

15

What is the reason Python doesn't have switch statement?

+1  A: 

Probably because, like in Perl, you don't need it to express the same thing?

I admit I appreciate Ruby having one though, it makes code cleaner than a series of if..elsif..else. YMMV :)

Keltia
+6  A: 

While I'm not experienced with using python I was intrigued by your question since I incorrectly assumed that most modern languages contained a switch statement...

So I did some searching via google and found the following link to provide a fairly good answer:

http://www.python.org/dev/peps/pep-3103/

Seems there is little popular support for it....but I'll let that article do the explaining...

mezoid
Lua doesn't have switch either, officially, but the code is in thereto be activated.
Robert Gould
+18  A: 

It was proposed and rejected in PEP 3103. I don't know why it didn't have it initially. There's an idiom I saw here that can replace the switch statement by using a dict of value and actions:

{'option1': function1,
 'option2': function2,
 'option3': function3,
 'option4': function4,
}.get(value, defaultfunction)()

And there's always the if-elif-else chain.

haggai_e
yeah.. but, why?
bobobobo
+10  A: 

PEP 3103 just talks about adding the switch statement to Python. This suggestion was rejected by Guido.

Quoting Guido:

A quick poll during my keynote presentation at PyCon 2007 shows this proposal has no popular support. I therefore reject it.

As a workaround, you may say something like this:

result = {
  'a': lambda x: x * 5,
  'b': lambda x: x + 7,
  'c': lambda x: x - 2
}[value](x)
bgbg
Beware that, when using this workaround, adding a "default" clause is not straightforward — you must wrap the entire construct in a `try: … catch KeyError:` block.
Ben Blank
+3  A: 

You have

if ... elif... elif... elif... else

And you have

{
 key1: value,
 key2: lambda : someFunction(),
 key3: lambda :anything(),
 key3: lambda x, y: someFunctionWithManyParams(x,y, 15, "abc")
}.get(key, defaultValue) 

which is quite powerful idiom.

EDIT: Improved as suggested in comments (thanks!)

Abgan
The problem with the one you show is that every value will be evaluated, no matter what they value of the key is (so "someFunction()" and "anything()" will run, even if key == key1). @bgbg showed a better version.
Joachim Sauer
@saua: I prefer @haggai_e's version -- fewer lambda's.
S.Lott
@saua: It's the same idea as the others'. Abgan just did it wrong (No offense, Abgan... It was probably a typo).
Jeremy Cantrell
Well, I don't emulate switch often enough it seems... You're right that all functions in my version would be called unconditionally. I can only apologise :-)
Abgan
You have to actually call the result in the case of the lambdas. Keys also need to be quoted, but that's more nitpicky. :)
cdleary
I consider key1, key2 and so on to be some defined constants (I try to NEVER use arbitrary strings/numbers in code, but use named constants instead).And I don't want to call everything I fetch from the dict, as I can get plain value or function with/without parameters. All this was intentional
Abgan
if elif elif ... else generally has much worse performance than a switch statement once you get past something like 3 or 4 cases. The costs for the two patterns grow at very different rates.
Harvey
+5  A: 

There are two reasons:

  1. switch() is actually a huge goto and with quite a few hidden semantics (like fall through, is break a label or a statement, what happens if you place "default" in the middle of the values and omit the "break", how do you break a look from inside a switch: continue will work but break won't).
  2. You can simulate switch() efficiently by using a dict where the keys are the values you want to match and the values are functions/methods. A corner case is using the methods of the current class and getattr(self, key).
Aaron Digulla
#1 is true of C-derived languages, but other languages (Pascal, Ada, Ruby) implement the switch concept in a much more structured manner. #2 is reason enough.
Ferruccio
I argue #1; often, when dealing with large switch statements with small ranges (0~20 for example), a switch is implemented as a jump table by the compiler. It's usually much faster, as it doesn't perform 22 comparisons (only two) for my example.
strager
+20  A: 

Switch is a popular code smell in many OO languages (when you follow OO paradigm) and in most of cases it indicates that there should be polymorphic call there. When you're about to write a switch, stop for a minute and double check you design. Perhaps you can make a polymorphic call instead.

Related question suggested in comments: http://stackoverflow.com/questions/126409/ways-to-eliminate-switch-in-code

Article about switch and other similar stuff by Misko Hevery: http://misko.hevery.com/2008/12/08/clean-code-talks-inheritance-polymorphism-testing/

More about Switch Statements Smell: http://c2.com/cgi/wiki?SwitchStatementsSmell

//Edited after suggestions in comments

Nazgob
"Switch is defective by design in OO languages" - that is one hell of a bold statement.
xan
A bit bold yes, but not far from true in my experience. See also the two most popular answer from http://stackoverflow.com/questions/126409/ways-to-eliminate-switch-in-code
Sébastien RoccaSerra
Any technical comment anybody? In OO languages you are not forced to use it. If you "do switch", you're probably not writing OO code which is not bad for some cases.
Nazgob
You may not be writing OO code, but OO isn't the only paradigm, even in OO-capable languages.
Greg Beech
Nazgob, is the if statement OO? I know where you're coming from, but you're overstating your point somewhat.
mackenir
People should be more careful about such overstatements, they only confuse the beginners and lead to flames. Switch can be perfectly fine in OOP, for example when you need to do some simple state processing.
zoul
Well, I know that for some ppl it's a heresy but hey -> you can write as much switches in your code as you want. It's engineering, we have to make hard choices. However it's good advice for beginners -> maybe it will force them to double check the design next time they will write switch.
Nazgob
Prior to the first example you linked to, I'd never seen switch used with typeof. Switch is USUALLY used with base types like numbers and strings, as an alternatively to nasty if/else if/else if/etc.../else blocks.
R. Bemrose
Well, it's an alternative but it's also kinda bad. Shouldn't those functions under if-s or cases be object with some method? If you apply "Extract Object" refactoring on those cases you will be in position to eliminate switch and make polymorphic call.
Nazgob
Ofc, it's not not a silver bullet. Switch is hint that deign MIGHT be wrong. Next problem is that somehow you need to inject proper object to make this polymorphic call. This is responsibility of a factory and sometimes you can move switch out of your business class to factory.
Nazgob
This argument doesn't really hold water because Python is a multi-paradigm language.
James McMahon
You should be more specific in your answer. `switch` is nothing but a limited syntactic sugar for a set of `if-else` branches. Factory methods /need/ this branching. Sometimes a factory's code looks nicer with a `switch` rather than an `if-else`. The same holds for recursive-descent parsers.
wilhelmtell
A: 

Even in languages that DO have a switch statement (C++ and Java being the ones I use mostly), I rarely use it. If you need to select from multiple code branches so that an if statement won't suffice, then, IMHO, you're doing it wrong.

If I need to select some code to run depending on the value of a variable, I find it much more powerful to do one of two things:

  1. Use the dictionary idiom described in other answers. This makes sense because to add new values to the allowed set of values, I don't need to maintain a switch statement, but rather add a new entry to a dictionary - this is especially useful if its used in more than one location (which is the biggest reason I dislike the switch statement).
  2. Basically, the same as above, but not in python - that is, Python makes it easy to stuff functions in dictionaries - Java or C++ may not, so I simulate this using classes which I derive from.

The point in both cases is to allow adding new values without needing to delve into the depths of the code and modify if or switch statements.

Dan
A: 

I say if they won't include it they should stop using it in the source code to python itself; then see who needs it :-p

I've heard of keeping your language pruned but seriously; switch is good :-p

widgisoft
i got u....my mistake
well said... bloodymindedness is the principle reason for Python to eschew switch... people are so proud of their silly workarounds, and have been arguing about it for so long, it's part of being a python fan. For evidence, note that Guido summarises the PEP rejection as being because the group of pythonistas at some conference weren't enthused about it... very rational.
Tony
A: 

Along with all of the other more detailed answers, I would add that a switch statement is simply unnecessary as one of the core ideas of the python language is that there should be one obvious way to do something.

Jeremy Cantrell
+13  A: 

The Python FAQ has this answer:

http://docs.python.org/faq/design.html#why-isn-t-there-a-switch-or-case-statement-in-python

projecktzero
the question was moved to another page, here is the new url http://docs.python.org/faq/design.html#why-isn-t-there-a-switch-or-case-statement-in-python
lesmana
The link is edited to the new url. Thanks @lesmana
MrValdez
A: 

"The Zen of Python", pasted below, leads you to the answer.

Read lines 13 and 14. After seeing examples of dicts used for switch functionality, it starts to click that this is the Pythonic way of doing a switch statement in a less error-prone, more human readable form.

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.  <-- 13
Although that way may not be obvious at first unless you're Dutch.     <-- 14
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

And, as others have mentioned, more verbose answers can be found in:

And here at stackoverflow there is a thread of proposed switch/case alternatives:

Jarred McCaffrey
+1  A: 

Fast note: If you want "fall-through" behavior, don't use an elif statement, because if it executes it exes the if-elif-else block. A series of pure "if" statements, however, will fall through.

You can nest "if" w/ fallthrough with "if-elif-else" statements, but it results in a very fertile ground for hard to catch bugs. Also, a trailing else executes if the test before it fails, even if one of the earlier "if" statements executed.

J.T. Hurley
A: 

I think that a switch case is needlessly redundant, something Python strives to avoid. Not to mention the amount of code you'd have to write in python is virtually the same, if not less since you don't need break statements.

Python

if blah == 1:
    do_something
elif blah == 2:
    do_something
elif blah == 3:
    do_something

Switch

switch(blah)
{
    case 1:
    do_something;
    break;

    case 2:
    do_something;
    break;

    case 3:
    do_something;
    break;
}
Soviut
I disagree. There is a performance reason for a switch and in many cases it makes for cleaner code.
James McMahon
In terms of languages like python, how it would handle a switch statement may very well get treated exactly like an if. Worrying about the performance of logic systems is a slippery slope to pre-optimization deadlock. Likewise, all the PEPs that suggest implementations have NOT been cleaner.
Soviut
A: 

switches, returns, for loops, while loops and if/else statements are all just contrived versions of goto, hangovers from the procedural programming days. Like drugs, they provide a quick satisfying fix, but in the long run they wreck health and cause other problems:-

  • By exponentially increasing the number of code paths, they make code unreadable.
  • By making special-case behaviour implicit and hidden they make code fragile.
  • By wrapping up logic inside conditions and blocks, they prohibit extension.

Code is a lot better off without them.

It is perfectly possible to program without directly using any of these statements, and programs written in this way are almost always more elegant, more flexible, and easier to understand and often a lot faster, because we can easily use better algorithms and don't spend so much time checking cases.

This is the point of object oriented programming. Anyone can make a class that is essentially a placeholder for a bunch of switch statements, but that just isn't OOP.

So what is OOP?

  • Using classes instead of conditionals and cases, so you can easily extend your software.
  • Using recursion instead of while loops, so you can easily define complex algorithms.
  • Using iterators instead of for loops, so you can easily use different containers.
  • Using callbacks instead of returns, so you can easily scale your system.

I hope this is useful to you.

Wait... so are proposing removing all code flow statements. You need a conditionals at some point or another, I don't care how OO correct your code is.And recursion instead of while loops... that is just plain bad advice.
James McMahon
He's right actually. There's an excellent google video about how to model without conditions. It may seem unorthodox, but its sound and practical.
Soviut
Managing 10x more classes makes it so much more easier to understand
Eric
James: yes, remove all code flow statements, why use them if class-based polymorphism does it better? I'm not saying remove *conditional behaviour*, just that there are *better ways of achieving it*. As for while loops, once written, how can we change their behaviour without changing their source code? Recursive algorithms with polymorphism are much more flexible. Note how functional languages benefit from not using while loops. I've given reasons for my views, just stating "that's plain bad advice" without supporting argument doesn't help anyone.
Eric: yes, you are quite right, managing 10 meaningfully named classes, each with 10 meaningfully named methods is far, far less of a headache than managing 100 cryptic, anonymous, nested conditional blocks, with the odd out-of-date, misleading comment thrown in. 100 blocks is probably a conservative estimate of a non-OO equivalent; usually, without classes, code duplication is rampant, as everything is buried and non-reusable, so it will be more like 200-300 duplicated blocks. See: http://c2.com/cgi/wiki?FearOfAddingClasses A single path through a block of code is the best you can achieve.