1

If I have a function:

if a_string == "a" or a_string == "b" or a_string == "c":
    # do this

how can I write that differently without the repetitive or statements? Or is that the best way?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Brian
  • 151
  • 2
  • 9
  • Yeah, sorry, i just wrote this really quick – Brian Jan 21 '14 at 15:49
  • I rolled back your question because you've changed it to a different one, invalidating the answers, and the new one doesn't make much sense: no string can be equal to "a" and also equal to "b" and also equal to "c". – DSM Jan 21 '14 at 15:50
  • @Brian: Perhaps you should consider putting a little more effort in your questions then? We try to put time and thought into our answers, too! – Martijn Pieters Jan 21 '14 at 15:53
  • Oops, thanks.. should have thought that through. – Brian Jan 21 '14 at 15:53

5 Answers5

9
if a_string in ["a", "b", "c"]:
    # do stuff

Make sure you use == in your conditions, not =, or else Python will throw an error

EDIT: As Nigel Tufnel points out in his answer, you can also check for membership in a set, e.g. {'a', 'b', 'c'}. I believe this is actually faster in general, though it really won't matter practically if you only have three things in the list/set.

senshin
  • 10,022
  • 7
  • 46
  • 59
5

You can test for a list membership:

if a_string in ["a", "b", "c"]:
    # do your thing

or you can test for a set membership:

if a_string in {"a", "b", "c"}:
    # do your thing

or you can test for a tuple membership:

if a_string in ("a", "b", "c"):
    # do your thing

I think that the list way is the most pythonic way, the set way is the most right way, the tuple way is the most bizzare way.

EDIT: as DSM and iCodez have pointed out I was wrong: the tuple way is the fastest (probably not, see EDIT#2) and the most pythonic way. Live and learn!

EDIT#2: I know that microbenchmarking is the most evil thing since Adolf Hitler but I'm posting it anyway:

python -O -m timeit '"c" in ("a", "b", "c")'
10000000 loops, best of 3: 0.0709 usec per loop

python -O -m timeit '"c" in ["a", "b", "c"]'
10000000 loops, best of 3: 0.0703 usec per loop

python -O -m timeit '"c" in {"a", "b", "c"}'
10000000 loops, best of 3: 0.184 usec per loop

I won't interpret the timeit results but the set timing is rather peculiar (probably it's because of the, er, I won't interpret the results).

Nigel Tufnel
  • 11,146
  • 4
  • 35
  • 31
  • 1
    Why do you call the tuple way bizarre? By my rough count, it's 3-4 times as common as either of the others in the Python 2.7.4 source itself. – DSM Jan 21 '14 at 15:47
  • 1
    Also, in this case, the tuple would be the fastest solution. ;) –  Jan 21 '14 at 15:47
  • Out of curiosity, why is the tuple the fastest solution? I've always heard that membership testing in a set (and a frozenset) is significantly faster than in a list, which seems to makes sense since lookup times can be faster than O(n). Is it just because the set/tuple involved here is very small? – gms7777 Jan 21 '14 at 15:57
  • 1
    @gms7777 - Yes, that is exactly it. As this [link](http://technobeans.wordpress.com/2012/04/09/performance-for-testing-memberships-list-vs-tuples-vs-sets/) will demonstrate, it all comes down to the size of the collection. Using a tuple or a list is a lot more efficient when dealing with *small collections*. However, a set is *much* faster with larger ones. –  Jan 21 '14 at 16:41
0

Try:

if a_string in ["a", "b", "c"]:
    do this
Ben March
  • 566
  • 3
  • 12
0
if a_string in ("a", "b", "c"):
    # do this

And you have an error in your example. Assignment "=" is not allowed in the "if" statement. You should use "==".

Dmitry Vakhrushev
  • 1,382
  • 8
  • 12
0

To add to the previous, in the specific case of checking for a single character in a string, you can do this:

if a_string in "abc":

Another similar idiom that you are likely to find useful is this:

Instead of:

if a_string == "abcdefg" or b_string == "abcdefg" or c_string == "abcdefg":

You can do this:

if any(i == "abcdefg" for i in (a_string, b_string, c_string)): 
rlms
  • 10,650
  • 8
  • 44
  • 61