Does python prioritize True in ‘or’ and False in ‘and’ condition checks?

Naveen Mathew Nathan S.
4 min readOct 31, 2021

Background

I found this meme on LinkedIn recently. After reading this post I hope people feel the same about python.

Experimenting with ‘and’

Let’s assume we have a simple function in python to check if all the numbers in a list are greater than a threshold. Logically the function should return False if any number in the list violates the condition. Therefore, a single False is sufficient to make all([…, False, …]) return a False. Similarly, a single True is sufficient to make any([…, True, …]) return a True. Therefore, if ‘n’ is the length of the list, the number of steps required to determine the output should be strictly less than or equal to n. However, things may become interesting if we use a recursive function instead of a loop to obtain the result. Consider the following function:

Defining the all_greater function

It is well known that recursive functions use a “call stack”. Consider the following function call and try to reason how many times print(1) will be executed:

Surprisingly (or unsurprisingly), the answer is — just once! Let’s change the order of conditions under ‘else’ and see what happens:

Surprisingly, the function was called 100 times! Despite the fact that and([A, B]) == and([B, A]), and nums[0] > threshold is violated for the very first index, the recursive call was made to the function. Therefore, we can conclude that the statement on the left is given preference during the evaluation of ‘and’ condition.

Experimenting with ‘or’

Unsurprisingly, the same pattern is observed with True and ‘or’. However, it only gets more mysterious from here.

Enter numpy

More experiments with ‘and’

This arises naturally from the following:

False and A = A and False = False

True and A = A and True = A

More experiments with ‘or’

False or A = A or False = A

True or A = A or True = True

Surprisingly, np.nan or True -> nan! This contradicts A or True = True. At present I’m unable to think of a reasonable explanation for this result.

The mystery does not end there

Mysteriously, all the statements resulted in True / False outputs. The most intriguing results were:

While np.nan.__bool__() -> True explains all these observations, it does not explain why np.nan or True -> nan instead of True (simplified).

Conclusion

Logical ‘or’ and ‘and’ statement in python seem to execute the statement on the left before executing the statement on the right. “A and False = False and A = False” and “True or B = B or True = True” can reduce the number of call stacks in a recursive function if the output is simply ‘and([List])’ or ‘or([List])’.

Handling missing boolean values in numpy is not very intuitive. Using numpy’s logical_and / logical_or may lead to inconsistent outputs that may pass unit tests, but can lead to incorrect results during runtime.

Additional Reading

Please look at the following articles for more interesting observations on python’s handling of logical expressions:

--

--

Naveen Mathew Nathan S.

Data Scientist, interested in theory and practice of machine learning.