Python最佳实践:“or”或“in”系列?

时间:2016-10-10 14:45:28

标签: python performance python-3.x

我正在project处理有关以下行的问题:

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唯一说的(我能找到):

  

...代码的读取频率远高于编写代码。此处提供的准则旨在提高代码的可读性......

     

然而,知道何时不一致 - 有时风格指南建议不适用。如有疑问,请使用您的最佳判断。查看其他示例并确定最佳效果。

3 个答案:

答案 0 :(得分: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 :(得分: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),
])

答案 2 :(得分:1)

正如多人所建议的那样,寻求恢复。

性能方面存在差异,集合上的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