使用Python字典代替switch/case
我最近了解到,Python没有switch/case语句。于是我开始研究用字典来代替,比如下面这个例子:
values = {
value1: do_some_stuff1,
value2: do_some_stuff2,
valueN: do_some_stuffN,
}
values.get(var, do_default_stuff)()
我搞不明白的是,如何用这个方法来做范围测试。也就是说,不是说如果value1=4
就做某些事情,而是如果value1<4
就做某些事情。像这样(我知道这样是不行的):
values = {
if value1 <val: do_some_stuff1,
if value2 >val: do_some_stuff2,
}
values.get(var, do_default_stuff)()
我尝试用if/elif/else语句来实现这个功能。虽然这样可以正常工作,但感觉比我不需要if语句的情况要慢很多(这可能是显而易见的,也是不可避免的)。所以这是我用if/elif/else语句写的代码:
if sep_ang(val1,val2,X,Y)>=ROI :
main.removeChild(source)
elif sep_ang(val1,val2,X,Y)<=5.0:
integral=float(spectrum[0].getElementsByTagName("parameter")[0].getAttribute("free"))
index=float(spectrum[0].getElementsByTagName("parameter")[0].getAttribute("free"))
print name,val1,val2,sep_ang(val1,val2,X,Y),integral,index
print >> reg,'fk5;point(',val1,val2,')# point=cross text={',name,'}'
else:
spectrum[0].getElementsByTagName("parameter")[0].setAttribute("free","0") #Integral
spectrum[0].getElementsByTagName("parameter")[1].setAttribute("free","0") #Index
integral=float(spectrum[0].getElementsByTagName("parameter")[0].getAttribute("free"))
index=float(spectrum[0].getElementsByTagName("parameter")[0].getAttribute("free"))
print name,val1,val2,sep_ang(val1,val2,X,Y),integral,index
print >> reg,'fk5;point(',val1,val2,')# point=cross text={',name,'}'
这段代码检查大约1500个变量sep_ang的值,差不多要花5分钟。而如果我不想用setAttribute()根据sep_ang的值来改变xml文件中的值,我就用这个简单的if else:
if sep_ang(val1,val2,X,Y)>=ROI :
main.removeChild(source)
else:
print name,val1,val2,ang_sep(val1,val2,X,Y);print >> reg,'fk5;point(',val1,val2,')# point
这样只需要大约30秒。再说一次,我知道加上那个elif语句并改变属性值肯定会大大增加代码的执行时间,我只是好奇有没有什么办法可以绕过这个问题。
编辑: 在我的情况下,使用bisect而不是if/elif语句的好处是,它可以更快地检查某个范围内的值,而不是使用一堆elif语句吗?
看起来我还是需要用elif语句。比如这样:
range=[10,100]
options='abc'
def func(val)
return options[bisect(range, val)]
if func(val)=a:
do stuff
elif func(val)=b:
do other stuff
else:
do other other stuff
所以我的elif语句只是在检查一个单一的值。
非常感谢你的帮助,我非常感激。
6 个回答
虽然字典这种方法对于单个值很有效,但如果你想处理范围的话,使用if ... else if ... else if
可能是最简单的办法。
如果你只想找一个单一的值,字典是个不错的选择,因为字典就是用来做这个的。但如果你想处理一个范围,字典就不太适用了。你可以用dict
来做,像这样:
values = {
lambda x: x < 4: foo,
lambda x: x > 4: bar
}
然后你需要遍历字典里的所有键值对,传入你的值作为键,如果键对应的函数返回真,就执行这个值作为函数。
不过,这样做其实并没有比多个if
语句更好,而且还会让维护和调试变得更困难。所以还是别这样做,直接用if
就好了。
字典并不是解决这个问题的合适结构。bisect
的例子展示了如何进行这种范围测试的一个例子。
终于搞明白该怎么做了!
我没有用一堆elif语句,而是这样做:
range=[10,100]
options='abc'
def func(val)
choose=str(options[bisect(range,val)])
exec choose+"()"
def a():
do_stuff
def b():
do_other_stuff
def c():
do_other_other stuff
这样不仅能正常运行,而且速度几乎和我原来的四行代码一样快,原来的代码里我没有改变任何值!