Remember your in operator
After you have worked with Python for a while you develop a sense that tingles when you are doing something that feels stupid, or wrong, on unaesthetic. I have found that more often than not someone before me apparently felt the same, and there is a more elegant, or Pythonic way of doing it. One of the simplest cases I find is with the in operator. Consider the following code:
if a == 1 or a == 7 or a == 15: do_some_cool_stuff()
This might be a personal pet peeve of mine, but that just feels tedious and somewhat prone to errors. Luckily there is a neater way of doing it using the in operator:
if a in (1, 7, 15): do_some_cool_stuff()
There, much less typing, and it looks nice, too!
Performance wise there isn’t that big a difference, at least on 32-bit Linux with CPython. Here are some comparisons with the help of ipython and timeit:
In [1]: a=16 In [2]: timeit a == 1 or a == 7 or a == 15 10000000 loops, best of 3: 167 ns per loop In [3]: timeit a in (1, 7, 15) 10000000 loops, best of 3: 155 ns per loop In [4]: timeit a in [1, 7, 15] 10000000 loops, best of 3: 157 ns per loop In [5]: a=1 In [6]: timeit a == 1 or a == 7 or a == 15 10000000 loops, best of 3: 72.4 ns per loop In [7]: timeit a in (1, 7, 15) 10000000 loops, best of 3: 83.4 ns per loop In [9]: timeit a in [1, 7, 15] 10000000 loops, best of 3: 83.5 ns per loop
Similar Posts:
- None Found



tasc:
notice that in the second set of comparisons, if you change a = 1 to a = 15 you will see a slightly different picture
June 17, 2009, 8:16 amArmin Ronacher:
If the contents of the tuple are constant values, use a tuple instead of a list. Then the whole tuple is stored in the code instead of the opcodes to create it / the list.
August 11, 2009, 11:28 amtasc:
@Armin: in this particular case set would be more appropriate.
August 11, 2009, 11:43 amssadler:
@tasc, why is that? Are sets more efficient for this operation?
August 11, 2009, 12:12 pmtasc:
sets are hashes, in is a O(1) operation
August 11, 2009, 12:36 pmtdrusk:
Cool. I am just getting used to Python. I am starting to get that tingly feeling you described.
It took me a minute to figure out what you were doing with the list, but after reading a comment or two I realized that I had to do this for one number.
x=10
if x in (10,):
print ‘hello’
I suppose there’s more than one way to skin a cat.
August 11, 2009, 1:35 pmssadler:
@tdrusk: I don’t think it really improves readability to do it for one number.
August 11, 2009, 1:44 pmErnie:
Using set is faster than using 3 comparisons. So using in looks best and is fastest.
In [1]: a=16
In [2]: s=set([1,7,15])
In [3]: timeit a==1 or a==7 or a==16
10000000 loops, best of 3: 126 ns per loop
In [4]: timeit a in s
August 11, 2009, 8:15 pm10000000 loops, best of 3: 107 ns per loop
lorg:
@Ernie:
August 11, 2009, 10:55 pmNote that your comparison isn’t really fair, as you don’t take into account the time spent building the set.
Since usually you won’t reuse the set for other comparisons, and the idiom is “a in set([...])”, you should take it into account. See:
In [2]: a = 16
In [3]: timeit a==1 or a==7 or a==16
10000000 loops, best of 3: 144 ns per loop
In [4]: timeit a in set([1,7,15])
1000000 loops, best of 3: 786 ns per loop
Ernie:
@lorg
if you know enough about the logic of your program to hardcode a==1 or a==7 or a==15, then you know enough to hardcode set([1,7,15]) outside the loop.
Creating the set takes ~6 times longer than doing one hardcoded comparison, but further comparisons are quite a bit faster. I think the choice of what to use depends on how many times you’ll execute the statement. But there should never be a case you create the set repeatedly.
August 12, 2009, 1:19 am