if 'a' or 'b' in L, where L is a list (Python)

Question:

I am having trouble with the following logic:

Lets say I have a list L = ['a', 'b', 'c']


Both items are in the list…

if ('a' or 'b') in L:
    print 'it's there!'
else:
    print 'No sorry'

prints It's there!


Only the first item is in the list…

if ('a' or 'd') in L:
    print 'it's there!'
else:
    print 'No sorry'

prints It's there!


Neither item in the list…

if ('e' or 'd') in L:
    print 'it's there!'
else:
    print 'No sorry'

prints No sorry


Here’s the confusing one Only the second item in the list…

if ('e' or 'a') in L:
    print 'it's there!'
else:
    print 'No sorry'

prints No sorry


I do not understand why this is not registering as a true statement. How does this generalize to an or statement with n conditionals?

Forehead-slapping easy answer in 3,2,1…

Asked By: Brian Leach

||

Answers:

Use this instead:

 if 'a' in L or 'b' in L:

If we want to check if all these of this “items” are in the list, all and a generator comprehension is your friend:

items = 'a', 'b', 'c'
if all(i in L for i in items):

Or if any of these items are in the list, use any:

if any(i in L for i in items)
Answered By: aIKid

Let’s break down the expression:

('e' or 'a') will first check if 'e' is True. If it is, the expression will return 'e'. If not, it will return 'a'.

Since all non-empty strings returns True, this expression will always return 'e'. This means that if ('e' or 'a') in L: can be translated to if 'e' in L, which in this case is False.

A more generic way to check if a list contains at least one value of a set of values, is to use the any function coupled with a generator expression.

if any(c in L for c in ('a', 'e')):
Answered By: Steinar Lima

Strings (except an empy string) will always evaluate to True when they are evaluated as a boolean. While evaluating with or/and both will return True, but there is a little difference between them:

print 'a' or 'b'    # Output:  a
print 'a' and 'b'   # Output:  b

or: will return the first string
and: will return the last string

When you do

if ('a' or 'b') in L:

, it will check 'a' or 'b' which is 'a' and then check if 'a' is in L. Something similar happens with the other cases (based on what I explained before).

So when you do

if ('e' or 'a') in L:

, 'e' or 'a' will evaluate to 'e' and therefore it will print 'No Sorry', because 'e' is not in L.

What you must do is compare whether elements are in the list separately:

if 'a' in L or 'b' in L:
if 'a' in L or 'd' in L:
if 'e' in L or 'd' in L:
if 'e' in L or 'a' in L:
Answered By: Christian Tapia

The trick to the output you’re getting is that and and or in Python always evaluate to one of their operands — generally the one that had to be evaluated last to determine the truthiness of the operation:

1 or 2  # returns 1 because since 1 is true, there's no need to evaluate the second argument.
1 or 0  # returns 1, same thing.
0 or 2  # returns 2 because 0 is false, so we need to evaluate the second arg to check whether the operation is true.
0 or "" # returns "" (both 0 and "" are false).

1 and 2    # returns 2 because for an and operation to be true, both its operands need to be checked for truthiness.
0 and 2    # returns 0, because we know that if the first operand is false, so is the whole operation.
0 and None # Still returns 0, we don't even need to check the second operand.

So when you’re evaluating (1 or 2) in [1, 3, 5] (where in truth you want 1 in [1, 3, 5] or 2 in [1, 3, 5]), what really happens is (1 or 2) is evaluated to 1, and your operation becomes 1 in [1, 3, 5].

Answered By: Max Noel
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.