Disjunction and membership in python

Question:

When I try this code:

a = ['b']

if 'i' or 'j' in a:
    print('Yes!')
else:
    print('No!')

The output is ‘Yes!’. Flake8 and python do not complain about an error or bad form.

What exactly happens when the code runs? Why does 'i' or 'j' in a evaluate as true?

Answers:

The problem is that in the statement i evaluates to True, which means that the statement is then: True or 'j' in a. This is always true and your result will be always ‘Yes!’.

You can use something like this to check if one of the values is in your list:

a = ['b']
chars_to_check = ['i', 'j']

filtered_list = [i for i in a if i in chars_to_check]

if len(filtered_list)>0:
    print('Yes!')
else:
    print('No!')

The example is from this question, where people also posted more efficient or shorter solutions to your problem. The solution I like the most would be this one:

a = ['b']
if {'i','j'} & set(a):
    print('Yes!')
else:
    print('No!')

EDIT: I think now I understand the question.

First of all python sees that you have a or in your if statement. This means the first expression (in your case 'i') is evaluated first. If the first expression is True, the whole statement is True and the second expression is not even evaluated. The evaluation order of or is explained here for example.

Now to why the first expression is always True. Python automatically evaluates all objects not only boolean values. For this the objects can for example contain a function __bool__() that gives back the boolean value of an object. The object in your case is a single character 'i', which evaluates to True. The reason is that it is defined that the boolean value of a string is always True except for the empty string (''). Here you can see an example of the evaluation:

print(bool('i')) # True
print(bool('')) # False

An answer that shows which objects are considered False and which are considered True can you find here.

Answered By: JANO