Friday, April 08, 2011

Python switch statement

Having a bit of fun at 3 in the morning.

The Python version of the C-style switch statement is either a bunch of if/else's or a dictionary. Going the dictionary route can be ugly looking (not to mention confusing, pulling a value out of a mapping and calling it). This just encapsulates the whole thing and adds some support for a pseudo-default case.

The structure is a bit weird, nowhere near as nice as regular syntax, but if you absolutely have to do this, it makes it easier to read.

"""A simple function (roughly) implementing C-style switch statements.
Usage::
switch(value, {
'it':
"You said the word!",
'fruit':
"Suppose he's got a pointed stick.",
'camelot':
"'Tis a silly place.",
Ellipsis:
("You've got two empty halves of coconut and you're " +
"bangin' 'em together.")
})
Also accepts *args and **kwargs, which will get passed on to the
specified case if it is callable.
The result of the callable is returned, as is the value of
non-callables.
Since `default` isn't a built-in name (and obviously not a statement),
the under-used built-in singleton Ellipsis is used in its place under
the assumption that it is unlikely to be used as a real case.
Fortunately, in the event that it *is* used as a real case, using
Ellipsis as the switch value will properly select the Ellipsis case.
Unfortunately, so will a non-match. It's probably best you don't use
Ellipse as a real case.
Finally: implicit break, no fall-through at all. Ever. First of all,
dict isn't ordered, so fall-through would be weird. Second, I'm not
going to specialize for OrderedDict (plus it would look weird on your
end), and third, I have no idea how to put breaking in if I did. If you
want this, do it yourself.
"""
def switch(value, cases, *args, **kwargs):
try:
case = cases[value]
except TypeError:
raise TypeError("Cases must be scriptable.")
except KeyError:
case = cases[Ellipsis] if Ellipsis in cases else None
finally:
try:
return case(*args, **kwargs)
except TypeError:
return case
def main():
import sys
try:
value = sys.argv[1]
except IndexError:
value = None
print switch(value, {
'it':
"You said the word!",
'fruit':
"Suppose he's got a pointed stick.",
'camelot':
"'Tis a silly place.",
Ellipsis:
("You've got two empty halves of coconut and you're " +
"bangin' 'em together.")
})
if __name__ == "__main__":
main()
view raw switch.py hosted with ❤ by GitHub

No comments:

Post a Comment