[英]Python dictionary instead of 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.
要做一些事情,如果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,'}'
這需要接近5分鍾來檢查var sep_ang的1500個值。 好像我不想使用setAttribute()根據sep_ang的值更改我的xml文件中的值,我使用這個簡單的if if:
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語句只檢查單個值。
非常感謝您的幫助,非常感謝。
字典是錯誤的結構。 bisect
示例顯示了此類范圍測試的示例。
雖然字典方法適用於單個值,但如果你想要范圍, if ... else if ... else if
可能是最簡單的方法。
如果你正在尋找一個單獨的值,這是一個很好的匹配字典 - 因為這是字典的用途 - 但如果你正在尋找一個范圍它不起作用。 你可以使用dict
這樣做:
values = {
lambda x: x < 4: foo,
lambda x: x > 4: bar
}
然后循環遍歷字典中的所有鍵值對,傳遞您的值鍵並在鍵函數返回true時將值作為函數運行。
但是,這對於許多if
語句沒有任何好處,並且更難維護和調試。 所以不要這樣做,而只是使用if
。
在這種情況下,您將使用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()
請注意,這實際上比嘗試使用字典要小。
dict
不是為了做這個(也不是切換!)。
一些海報提出了一個帶有遏制功能的字典,但這根本不是你想要的解決方案。 它是O(n)(就像一個if語句),它不起作用(因為你可能有重疊的條件),是不可預測的(因為你不知道你將做什么順序循環),並且不太明確比等價的if語句。 if語句可能是你想要的方式,如果你有一個短的,靜態長度的條件列表來應用。
如果您有大量的條件,或者如果它們可能因您的程序而發生變化,那么您需要不同的數據結構。 您可以實現二叉樹或保留排序list
並使用bisect
模塊查找與給定范圍關聯的值。
我不知道任何切實可行的解決方案。 如果你想猜測它會做什么,雖然你可以做這樣的事情:
obsure_switch = {
lambda x: 1<x<6 : some_function,
...
}
[action() for condition,action in obscure_switch.iteritems() if condition(var)]
終於弄明白該怎么辦了!
因此,我沒有使用一堆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行代碼一樣快,我沒有改變任何值的東西!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.