pycoder pycoder - 1 month ago 8
Python Question

Python best practice: series of "or"s or "in"?

I am working on a project where a question came up about the following line:

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


I proposed a change to make it "simpler" like so:

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


What would be considered best practice and what would be best for performance? This is for user interface code that gets updated frequently so minor performance improvements could be noticeable. I know the first example will "fail fast" if any were found, and I am assuming that the second would as well.

Furthermore, wouldn't it be even faster to use a dict like:

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


...so that a list wouldn't need to be constructed?

The only thing PEP-8 says (that I could find):


...code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code...

However, know when to be inconsistent -- sometimes style guide recommendations just aren't applicable. When in doubt, use your best judgment. Look at other examples and decide what looks best.

Answer

I'd go with the set. It's much more readable. The string of ors can be faster in some circumstances since the operator short circuits and there is no overhead of constructing the list of items each time but I don't think it's worth the readability sacrifice. Here is a quick and dirty benchmark. This is with 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