在Python中是沒有Switch / Case語句的,不少人認爲這種語句不夠優雅靈活,在Python中用字典來處理多條件匹配問題字典會更簡單高效,對於有必定經驗的Python玩家不得不認可,的確如此。python
但今天咱們仍是來看看若是必定要用Python來Switch / Case,能夠怎麼玩。編程
咱們先定義一下Switch/Case應該怎麼表達,爲了簡單咱們可讓它長成這樣。編程語言
def cn(): print('cn') def us(): print('us') switch(lang).case('cn',cn) .case('us',us) .default(us)
經過以上約束,咱們能夠把switch當成一個類來實現,傳入的參數在構造函數裏處理,而後再分別實現case和default方法便可。函數
class switch(object): def __init__(self, case_path): self.switch_to = case_path self._invoked = False def case(self, key, method): if self.switch_to == key and not self._invoked: self._invoked = True method() return self def default(self, method): if not self._invoked: self._invoked = True method()
在構造函數中咱們記住了case_path
和執行狀態_invoked
,在case()
裏若是當前的key
和switch_to
匹配而且函數沒有被執行過,那麼就更新_invoked
並執行對應的方法。在default()
裏檢查一下_invoked
,若是從沒執行過,那麼就調用default
分支的函數。測試
看上去還不錯,咱們來試用一下。ui
switch('cn').case('cn',cn).case('us',us).default(fail) >>> cn switch('us').case('cn',cn).case('us',us).default(fail) >>> cn switch('jp').case('cn',cn).case('us',us).default(fail) >>> fail switch('cn').case('cn',cn).case('us',us) >>> cn
讓咱們來看幾個奇葩一點的case。spa
# duplicate case switch('us').case('us',cn).case('us',us).default(fail) >>> cn def cn() return 'cn' def us() return 'us' # return value result = switch('cn').case('cn',cn).case('us',us) result >>> <python_switch_case.switch object at 0x11034fb70>
發現了沒有,上面的實現不會處理重複的case,固然你能夠增強一下case方法,最好是拋出異常,其餘編程語言一般都這樣作。rest
第二個問題,你但願從case裏拿到返回值,像上面的寫法是沒但願了,由於扔掉了。咱們能夠考慮在switch類里加一個result的變量來保存執行結果。code
class switch(object): def __init__(self, case_path): ... self.result = None def case(self, key, method): ... self.result = method() ...
在調用結束後,就能夠經過result
拿到結果了。ip
_ = switch('cn').case('cn',cn).case('us',us) _.result >>> cn
我大概在網上搜了一下,你還能夠參考Brian Beck經過類來實現Swich/Case。
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: self.fall = True return True else: return False c = 'z' for case in switch(c): if case('a'): pass # only necessary if the rest of the suite is empty if case('c'): 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!")
這種實現相對複雜一點,並且用起來也不是很舒服,又須要for又須要if(還不如直接if/else痛快)。固然也有好處,就是能夠把相同結果的case放一塊兒,並且case裏能夠寫更多東西,不單單是一個方法名。
最後咱們仍是回到Python推崇的方法來處理switch/case問題,通常咱們能夠經過字典來處理這種多分支的問題,舉例說明。
MAPPING = { 'cn': cn, 'us': us } lang = 'cn' result = MAPPING.get(lang, default=us)
是否是一目瞭然,不只易於閱讀也易於維護。在字典中key是惟一的,value能夠是任意類型的數據,能夠是類或者是方法,因此足夠靈活。
關於做者:Toby Qin, Python 技術愛好者,目前從事測試開發相關工做,轉載請註明原文出處。
歡迎關注個人博客 https://betacat.online,你能夠到個人公衆號中去當吃瓜羣衆。