簡體   English   中英

Python字典而不是switch / case

[英]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=4value1<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM