星期四, 6月 06, 2013

Python 沒有 switch - case

雖然在用 Python,但還是算初學者,一堆指令的用法和細節,都常常要上網找語法來用。這次突然翻到,Python 沒有 switch - case,喔喔喔!!有人整理過各種程式語言的switch - case,想不到連古老的COBOL 85也有類似的語法,更不用講在Python之後的Ruby或Perl了。
我是還沒寫到這麼高階的功能啦,不過看看別人怎麼處理這個問題也好。其實,書上會寫,要用if...elif...elif...else來處理這個問題。但是也有人想直接改別人的c code或php code而不要重寫,所以才會想出這些處理方法。
主要的參考網頁為 azalea saysActiveState Code,其實可以看看ActiveState Code下面的討論串,原來一個簡單的問題,其實有蠻多不同的創意解決方案,而不是教科書上寫的單一教條。

第一個方法是用Dictionary,第二個方法其實也是用Dictionary,再加上lambda。第三個方法就比較貼近我想的,直接寫一個 class來處理,以下的code,是2005年Brian Beck 就寫好的,來自於ActiveState Code,在此宣告他們的版權。


## {{{ http://code.activestate.com/recipes/410692/ (r8)
# 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.
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 statements
# in each suite.
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'
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:
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.
## end of http://code.activestate.com/recipes/410692/ }}}

沒有留言:

//for syntaxhighlighter 3 //看一下載入的JS模組有哪些,不要的就刪掉 //end syntaxhighlighter 3