2016-10-10 29 views
3

我在project工作,其中一個問題就來了大概有以下行:Python最佳實踐:「或」或「in」系列?

a == "EQUAL" or a == "NOT EQUAL" or a == "LESS" or a == "GREATER" 

我提出了一個變化,使其「更簡單」,例如:

a in ["EQUAL", "NOT EQUAL", "LESS", "GREATER"] 

怎樣纔算最好練習和什麼對性能最好?這是針對經常更新的用戶界面代碼,因此可能會引起較小的性能改進。我知道如果發現任何一個例子,第一個例子會「快速失敗」,並且我假設第二個例子也是如此。

此外,豈不是更快的使用像一個字典:

a in {"EQUAL", "NOT EQUAL", "LESS", "GREATER"} 

...讓列表不會需要建設?

唯一PEP-8說(我能找到):

...代碼讀取更經常比被寫入。這裏提供的準則旨在提高代碼的可讀性...

但是,知道什麼時候不一致 - 有時風格指導建議不適用。如有疑問,請使用您的最佳判斷。看看其他例子,並決定什麼看起來最好。

+10

你'dict'是'set'但除此之外,它是一個很好的選擇。 – Matthias

+0

@Matthias一套設備的問題是什麼(除了缺乏訂單,這不是一個問題)? – JakeD

+2

一組沒有問題。只要使用它。 – Matthias

回答

3

我會隨着集。它更可讀。在某些情況下,由於操作員短路,並且沒有每次構建項目列表的開銷,所以字符串or s可能會更快,但我認爲這不值得犧牲可讀性。這是一個快速和骯髒的基準。這是與Python 2.7

def t1(x): 
    return (x == "Foo" or x == "Bar" or x == "Baz" or x == "Quux")                      


def t2(x): 
    return x in {"Foo", "Bar", "Baz", "Quux"} 

[2.7.9]>>> import timeit 
[2.7.9]>>> timeit.timeit(lambda : t1("Quux"))                             
0.22514700889587402 
[2.7.9]>>> timeit.timeit(lambda : t1("Foo"))                             
0.18890380859375 
[2.7.9]>>> timeit.timeit(lambda : t2("Quux"))                             
0.27969884872436523 
[2.7.9]>>> timeit.timeit(lambda : t2("Foo"))                             
0.25904297828674316 

Python 3數字。

[3.4.2]>>> timeit.timeit(lambda : t1("Quux")) 
0.25126787397312 
[3.4.2]>>> timeit.timeit(lambda : t1("Foo")) 
0.1722603400121443 
[3.4.2]>>> timeit.timeit(lambda : t2("Quux")) 
0.18982669000979513 
[3.4.2]>>> timeit.timeit(lambda : t2("Foo")) 
0.17984321201220155 
+1

有趣的是,當項目* *無效時,需要多長時間。 ' 「取得foobar」'。 – MisterMiyagi

+2

設置版本在更高版本的python中更具競爭力。在python2中,每次都重新構建集合。在後來的版本中,由於該集合從不發生變化,因此編譯器會在編譯時創建一個凍結集並對其進行緩存。 – Dunes

1

顯然在你的情況下,最好使用in運算符。它更具可讀性。

在更復雜的情況下,當它無法使用in操作,您可以使用allany功能:

operations = {'EQUAL', 'NOT EQUAL', 'LESS', 'GREATER'} 
condition1 = any(curr_op.startswith(op) for op in operations) 

condition2 = all([ 
    self.Operation == "EQUAL", 
    isinstance(self.LeftHandSide, int), 
    isinstance(self.RightHandSide, int), 
]) 
+0

這會比任何方法都糟糕,因爲你每次都在評估一切。無論如何,任何也都很慢。 –

+0

@PadraicCunningham它不會使用生成器。 – skovorodkin

+1

是的,但你直到你編輯,第二個仍然在列表中,所以你仍然評估他們每一次。 –

1

如多個人建議,去reability。

性能方面明顯存在差異,集合上的in運算符的平均查找時間爲O(1),而列表爲O(n)。你可以找到這個here

在您的情況下,可能性的列表是有限的,你幾乎不會注意到一個區別。但是,一旦這個列表變得非常大(談論數以百萬計),你可以注意到一個區別。

一個簡單的例子可以證明這一點:對於套:

operation = 9999999 
lookupSet = {i for i in range(0,10000000)} 
%timeit operation in lookupSet 
>> 10000000 loops, best of 3: 89.4 ns per loop 

其中具有列表:

operation = 9999999 
lookupList = [i for i in range(0,10000000)] 
%timeit operation in lookupList 
>> 10 loops, best of 3: 168 ms per loop