我最近了解到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,'}'
检查var sep_ang的1500个值需要接近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语句只检查单个值。
非常感谢您的帮助,非常感谢。
答案 0 :(得分:10)
字典是错误的结构。 bisect
examples显示了这种范围测试的一个例子。
答案 1 :(得分:4)
虽然字典方法适用于单个值,但如果需要范围,if ... else if ... else if
可能是最简单的方法。
如果你正在寻找单个值,这与字典很匹配 - 因为这是字典的用途 - 但是如果你正在寻找一个范围它不起作用。您可以使用dict
使用以下内容执行此操作:
values = {
lambda x: x < 4: foo,
lambda x: x > 4: bar
}
然后循环遍历字典中的所有键值对,传递值键并在键函数返回true时将值作为函数运行。
但是,这对于许多if
语句没有任何好处,并且难以维护和调试。所以不要这样做,而只是使用if
。
答案 2 :(得分:3)
在这种情况下,您将使用if / then / else。你也不能用开关来做这件事。
switch语句的想法是你有一个值V,你可以根据N个可能的结果来测试身份。您可以使用if-construct执行此操作 - 但是平均需要O(N)运行时。每次开关都会给你恒定的O(1)。
这显然不适用于范围(因为它们不易于清除),因此您对这些情况使用if-constructs。
实施例
if value1 <val: do_some_stuff1()
elif value2 >val: do_some_stuff2()
请注意,这实际上比尝试使用字典要小。
答案 3 :(得分:2)
dict
不是为了这样做(也不是切换!)。
有几张海报提出了一个带有遏制功能的字典,但这根本不是你想要的解决方案。它是O(n)(就像一个if语句),它不起作用(因为你可能有重叠的条件),是不可预测的(因为你不知道你将做什么顺序循环),并且不太明确比等价的if语句。 if语句可能是你想要的方式,如果你有一个短的,静态长度的条件列表来应用。
如果您有大量条件或者由于您的程序而可能会发生变化,那么您需要不同的数据结构。您可以实现二叉树或保留已排序的list
并使用bisect
模块查找与给定范围关联的值。
答案 4 :(得分:0)
我不知道任何切实可行的解决方案。如果你想使用猜测它做什么的方法,你可以这样做:
obsure_switch = {
lambda x: 1<x<6 : some_function,
...
}
[action() for condition,action in obscure_switch.iteritems() if condition(var)]
答案 5 :(得分:-2)
终于找到了要做的事情!
因此,我没有使用一堆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
它不仅可以工作,而且几乎和原来的4行代码一样快,我没有改变任何值的东西!