我想通过将字符串与正则表达式序列匹配来处理它。当我试图避免嵌套的 if-then 时,我正在考虑 switch-case。如何用Python编写以下结构?谢谢你
switch str:
case match(regex1):
# do something
case match(regex2):
# do sth else
我知道 Perl 允许人们这样做。有Python吗?
首先考虑为什么Python中没有case语句。所以重置你的大脑并忘记它们。
您可以使用对象类、函数装饰器或使用函数字典来实现相同或更好的结果。
这是一个简单的例子:
#!/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 语句也“失败”,例如:
switch(c) {
case 'a':
case 'b':
case 'c': do_abc();
break;
... other cases...
}
使用元组和可调用列表,您可以获得类似的行为:
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)
print
这使得找到的物品的顺序正确:1)抱起孩子,拥抱孩子; 2) 杀掉老鼠,捡起老鼠……用 C switch 语句以可理解的语法来完成同样的事情是很困难的。
还有许多其他方法可以模仿 C switch 语句。这是使用函数装饰器的一个(对于整数):
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 在 Programming Perl 中关于理解 Perl 上下文的说法:
除非你使用 Python 语言原生的习惯用法,否则你的 Python 编程将会很痛苦......
快速搜索显示了之前提出的“类似问题”,并有多种解决方法。 最喜欢的解决方案是 Mizard
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
(免责声明:我是作者)。 有了它,您可以执行以下操作,这与您在问题中给出的示例非常接近:
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。
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()
结果
>>> delegate("CantBeFound")
0: 'No match.'
>>> delegate("spam")
1: 'Matched spam.'
>>> delegate("eggs")
2: 'Matched eggs.'
>>> delegate("fish")
3: 'Matched fish.'
如果您指的是 Perl
给定 / 当输入 switch 语句时,那么在 Python 中实现这并不是一件容易的事。您需要实现“智能匹配”和其他重要的 Perl 习惯用法。你不妨用 Perl 写任何东西? 如果您指的是C 风格的 switch 语句,那么相比之下,这些相对来说是微不足道的。最推荐使用字典调度方法,例如:
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
Python从3.10版本开始支持switch语句。 下面是使用正则表达式和 Python 新的 switch 语句支持的示例: