Python中Switch—Case实现

学习Python过程中,发现没有switch-case,过去写C习惯用Switch/Case语句,官方文档说通过if-elif实现。所以不妨自己来实现Switch/Case功能。

  • 方法一
    通过字典实现
    1
    2
    3
    4
    5
    6
    def foo(var):
    return {
    'a': 1
    'b': 2,
    'c': 3,
    }.get(var,'error') #'error'为默认返回值,可自设置
  • 方法二
    通过匿名函数实现

    1
    2
    3
    4
    5
    6
    def foo(var,x):
    return {
    'a': lambda x: x+1,
    'b': lambda x: x+2,
    'c': lambda x: x+3,
    }[var](x)
  • 方法三
    通过定义类实现
    参考Brian Beck通过类来实现Swich-case

    This class provides the functionality we want. You only need to look at this if you want to know how this works. It only needs to be defined once, no need to muck around with its internals.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class switch(object):
def __init__(self, value):
self.value = value
self.fall = False

def __iter__(self):
"""Return the match method once, then stop"""
yield self.match
raise StopIteration

def match(self, *args):
"""Indicate whether or not to enter a case suite"""
if self.fall or not args:
return True
elif self.value in args: # changed for v1.5, see below
self.fall = True
return True
else:
return False

The following example is pretty much the exact use-case of a dictionary,but is included for its simplicity. Note that you can include statementsin each suite.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
v = 'ten'
for case in switch(v):
if case('one'):
print 1
break
if case('two'):
print 2
break
if case('ten'):
print 10
break
if case('eleven'):
print 11
break
if case(): # default, could also just omit condition or 'if True'
print "something else!"
# No need to break here, it'll stop anyway

break is used here to look as much like the real thing as possible, but
elif is generally just as good and more concise.
Empty suites are considered syntax errors, so intentional fall-throughs
should contain ‘pass’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
c = 'z'
for case in switch(c):
if case('a'): pass # only necessary if the rest of the suite is empty
if case('b'): pass
# ...
if case('y'): pass
if case('z'):
print "c is lowercase!"
break
if case('A'): pass
# ...
if case('Z'):
print "c is uppercase!"
break
if case(): # default
print "I dunno what c was!"

As suggested by Pierre Quentel, you can even expand upon the
functionality of the classic ‘case’ statement by matching multiple
cases in a single shot. This greatly benefits operations such as the
uppercase/lowercase example above:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import string
c = 'A'
for case in switch(c):
if case(*string.lowercase): # note the * for unpacking as arguments
print "c is lowercase!"
break
if case(*string.uppercase):
print "c is uppercase!"
break
if case('!', '?', '.'): # normal argument passing style also applies
print "c is a sentence terminator!"
break
if case(): # default
print "I dunno what c was!"

Since Pierre’s suggestion is backward-compatible with the original recipe,
I have made the necessary modification to allow for the above usage.

查看Python官方:PEP 3103-A Switch/Case Statement
发现其实实现Switch Case需要被判断的变量是可哈希的和可比较的,这与Python倡导的灵活性有冲突。在实现上,优化不好做,可能到最后最差的情况汇编出来跟If Else组是一样的。所以Python没有支持。
在业务上Switch/Case和If-elif实现优化上究竟最差是如何?有体会的童鞋欢迎评论分享探讨哈!O(∩_∩)O