how can I combine a switch-case and regex in Python
我想通过将字符串与正则表达式序列匹配来处理字符串。当我试图避免嵌套if-then时,我想到的是切换情况。如何在Python中编写以下结构?谢谢
1 2 3 4 5 | switch str: case match(regex1): # do something case match(regex2): # do sth else |
我知道Perl允许这样做。是Python吗?
首先考虑为什么Python中没有case语句。因此,请重新设置您的大脑,并忘记它们。
您可以使用对象类,函数修饰符或使用函数字典来获得相同或更好的结果。
这是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/usr/bin/env python import re def hat(found): if found: print"found a hat" else: print"no hat" def cat(found): if found: print"found a cat" else: print"no cat" def dog(found): if found: print"found a dog" else: print"no dog" st=""" Here is the target string with a hat and a cat no d o g end """ patterns=['hat', 'cat', 'dog'] functions=[hat,cat,dog] for pattern,case in zip(patterns,functions): print"pattern=",pattern case(re.search(pattern,st)) |
C样式的case / switch语句也"掉进去了",例如:
1 2 3 4 5 6 7 | switch(c) { case 'a': case 'b': case 'c': do_abc(); break; ... other cases... } |
使用元组和可调用对象列表,您可以获得类似的行为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | st="rat kitten snake puppy bug child" def proc1(st): print"cuddle the %s" % st def proc2(st): print"kill the %s" % st def proc3(st): print"pick-up the %s" % st def proc4(st): print"wear the %s" % st def proc5(st): print"dispose of the %s" %st def default(st): print"%s not found" % st dproc={ ('puppy','kitten','child'): [proc3, proc1], ('hat','gloves'): [proc3, proc4], ('rat','snake','bug'): [proc2, proc3, proc5]} for patterns,cases in dproc.iteritems(): for pattern in patterns: if re.search(pattern,st): for case in cases: case(pattern) else: default(pattern) |
这将正确找到找到的商品的顺序:1)抱起孩子,抱住孩子; 2)杀死老鼠,捡起老鼠...使用C switch语句以易于理解的语法很难做到这一点。
还有许多其他方法可以模仿C switch语句。这是一个使用函数修饰符的(整数):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | case = {} def switch_on(*values): def case_func(f): case.update((v, f) for v in values) return f return case_func @switch_on(0, 3, 5) def case_a(): print"case A" @switch_on(1,2,4) def case_b(): print"case B" def default(): print"default" for i in (0,2,3,5,22): print"Case: %i" % i try: case[i]() except KeyError: default() |
转述Larry Wall,Tom Christiansen,Jon Orwant在《 Perl编程》中有关理解Perl中的上下文的信息:
You will be miserable programming Python until you use the idioms that are native to the language...
快速搜索显示了一个类似的问题,该问题先前已被解决,但存在多种解决方法。可能最喜欢的解决方案是Mizard
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import re class Re(object): def __init__(self): self.last_match = None def match(self,pattern,text): self.last_match = re.match(pattern,text) return self.last_match def search(self,pattern,text): self.last_match = re.search(pattern,text) return self.last_match gre = Re() if gre.match(r'foo',text): # do something with gre.last_match elif gre.match(r'bar',text): # do something with gre.last_match else: # do something else |
您有关Perl样式转换语句的问题是模棱两可的。您引用了Perl,但是在示例中使用的是C风格的switch语句。 (有一个不推荐使用的模块在Perl中提供了C风格的switch语句,但是不建议这样做...)
如果您的意思是在类型切换语句时给Perl /,那么在Python中实现将不是一件容易的事。您将需要实现智能匹配和其他不平凡的Perl习惯用法。您还可以在Perl中编写任何内容吗?
如果您指的是C风格的switch语句,则相比而言,它们相对来说是微不足道的。最推荐使用字典分派方法,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import re def case_1(): print"case 1" return 1 def case_2(): print"case 2" return 2 def case_3(): print"case 3" return 3 def default(): print"None" return 0 dispatch= { 'a': case_1, 'g': case_2, 'some_other': case_3, 'default': default } str="abcdefg" r=[dispatch[x]() if re.search(x,str) else dispatch['default']() for x in ['a','g','z'] ] print"r=",r |
您正在寻找pyswitch(免责声明:我是作者)。使用它,您可以执行以下操作,这与您在问题中给出的示例非常接近:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from pyswitch import Switch mySwitch = Switch() @myswitch.caseRegEx(regex1) def doSomething(matchObj, *args, **kwargs): # Do Something return 1 @myswitch.caseRegEx(regex2) def doSomethingElse(matchObj, *args, **kwargs): # Do Something Else return 2 rval = myswitch(stringYouWantToSwitchOn) |
在我链接的URL上有一个更全面的示例。 pyswitch不仅限于打开正则表达式。在内部,pyswitch使用一个调度系统,类似于上面其他人给出的示例。我只是厌倦了每次需要那种分派系统时都要一遍又一遍地重写相同的代码框架的方法,所以我写了pyswitch。
如果要避免使用if-then,则可以基于以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import re # The patterns r1 ="spam" r2 ="eggs" r3 ="fish" def doSomething1(): return"Matched spam." def doSomething2(): return"Matched eggs." def doSomething3(): return"Matched fish." def default(): return"No match." def match(r, s): mo = re.match(r, s) try: return mo.group() except AttributeError: return None def delegate(s): try: action = { match(r1, s): doSomething1, match(r2, s): doSomething2, match(r3, s): doSomething3, }[s]() return action except KeyError: return default() |
结果
1 2 3 4 5 6 7 8 | >>> delegate("CantBeFound") 0: 'No match.' >>> delegate("spam") 1: 'Matched spam.' >>> delegate("eggs") 2: 'Matched eggs.' >>> delegate("fish") 3: 'Matched fish.' |