What is the reason Python doesn't have switch statement?
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 :)
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...
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.
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)
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!)
There are two reasons:
- 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).
- 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).
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
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:
- 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).
- 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.
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
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.
The Python FAQ has this answer:
http://docs.python.org/faq/design.html#why-isn-t-there-a-switch-or-case-statement-in-python
"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:
- the Python FAQ for a summary
- PEP 3103 for all the gory details
And here at stackoverflow there is a thread of proposed switch/case alternatives:
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.
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;
}
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.