-2

Suppose I want to check if a variable equals one of several values. Which of the following expressions should I use?

if s == 'one' or s == 'two' or s == 'three':
    pass

if s in ('one', 'two', 'three'):
    pass

if s in ['one', 'two', 'three']:
    pass

if s in {'one', 'two', 'three'}:
    pass

EDIT: From the answers / comments, I understood that:

  • The first variant is least recommended, the others are considered equally "pythonic".
  • The Performance differences in checking membership are negligible, for a short sequence. Tuples are least costly to create, sets require computing hashes.
  • The four variants are not equivalent in some edge cases:
    • The in operator checks for both identity and equality.
    • Logical or is short-circuited. I suspect that Membership tests of tuples and lists should be evaluated sequentially and thus be short-circuited, too.
    • Sets require hashable elements.
  • 1
    I usually use sets as complexity there is O(1). – Cleb Aug 03 '18 at 07:57
  • 1
    The last one is theoretically faster if you can reuse the set, but for only three items there is no substantial difference. – khelwood Aug 03 '18 at 07:58
  • 1. No 2. Ok 3. a bit more expensive than 2 but still Ok 4. More expensive to create, fastest check, good if the set is reused. – Klaus D. Aug 03 '18 at 07:58
  • 1
    Check also [this related question](https://stackoverflow.com/questions/7571635/fastest-way-to-check-if-a-value-exist-in-a-list). – Cleb Aug 03 '18 at 08:00
  • 1
    Note that they are not strictly all equivalent `==` checks equality but the `in` operator checks both equality or identity – Chris_Rands Aug 03 '18 at 08:04
  • Possible duplicate: [Using lists and tuples in Python if statements](https://stackoverflow.com/questions/12409457/using-lists-and-tuples-in-python-if-statements) – U13-Forward Aug 03 '18 at 08:10
  • @Chris_Rands: So `in` checks identity first, and then equality? – Nicolas Malebranche Aug 03 '18 at 09:03
  • 1
    @NicolasMalebranche Yes, see https://stackoverflow.com/a/48867273/6260170 – Chris_Rands Aug 03 '18 at 09:06

4 Answers4

1

I think the below three are the best:

if s in ('one', 'two', 'three'):
    pass

if s in ['one', 'two', 'three']:
    pass

if s in {'one', 'two', 'three'}:
    pass

But maybe still:

if s in {'one', 'two', 'three'}:
    pass

Is still the best

Timing

%timeit if 'one' in ('one', 'two', 'three'):pass

Output:

The slowest run took 21.60 times longer than the fastest. This could mean 
that an intermediate result is being cached.
10000000 loops, best of 3: 63.4 ns per loop

&

%timeit if 'one' in ['one', 'two', 'three']:pass

Output:

 10000000 loops, best of 3: 50.7 ns per loop

&

%timeit if 'one' in {'one', 'two', 'three'}:pass

Output:

10000000 loops, best of 3: 50.3 ns per loop

At the end i prefer set({}) because it is the fastest

and the tuple is the slowest it what i least prefer (in the tuple, list and set)

Community
  • 1
  • 1
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
  • 2
    You should really say *why* you think these are best – Chris_Rands Aug 03 '18 at 08:03
  • 1
    Good! I don't think you can draw clear conclusions from those timings though – Chris_Rands Aug 03 '18 at 08:10
  • I got different results. Sets took about 20% of the time of lists and tuples, which were both very similar. The test was finding a character in a collection of 52 characters, which is obviously a lot more than the asker was looking for, but probably a more applicable test for the efficiency of sets over lists and tuples. – Alistair Carscadden Aug 03 '18 at 08:27
1

With three values to check, it does not matter.

The first one if s == 'one' or s == 'two' or s == 'three': is arguably the less pythonic. It may be handy in the case where one of the value is much more likely than the other. In that case, you take advantage of lazy evaluation by placing the most likely values up front, thus avoiding evaluating the entire expression most of the time.

Using a set if s in {'one', 'two', 'three'}: carries the cost of creating the set O(n) hashes upfront, but will pay large dividends in the case where there are many variables to check, many times, or if the collection contains many duplicates.

The other two are mostly identical. I have a slight preference for a tuple which is immutable, vs a list, but that is for reasons not directly related to the question.

Timing the performance differences for the case of 3 values is not useful.

Reblochon Masque
  • 35,405
  • 10
  • 55
  • 80
1

You should use the set if you will repeat multiple times or have to deal with many alternatives.

However, if you only use it once, it is recommended to use tuples.

The first type is not recommended under any circumstances.

Zip.O
  • 11
  • 1
  • 4
0

You can use any of the options you proposed, though the first one if probably the less convenient to use.

The last option using set is supposed to be the most efficient in terms of performance, but it really depends on how long is your collection.

If you don't have thousands of entries in your collection, just use a list, it's more common and more flexible for any usage.

pybuche
  • 74
  • 7