DEV Community

Cezar Peixeiro
Cezar Peixeiro

Posted on • Edited on

Why Python lists and AND / OR operators return "stranger things"?

Let's suppose that you're working on a Python project and decide to use the Boolean operators and and or to compare some lists. After that, you have a heart attack when you get these outputs:

lst1 = [False, False, False]
lst2 = [True, False, True]

print(lst1 and lst2)
>>> [True, False, True]

Enter fullscreen mode Exit fullscreen mode

You begin to doubt of your sanity, because you're expecting at least a [False, False, False] list (the output if both lists were compared by indexes) and begin to look for a psychiatrist!!

HEY! Take it easy!!! This is not the way that and and or work with lists. Let me explain you this secret:

When you compare lists with these operators you're not comparing the values but if the list really has values inside it. It sounds a bit confusing, so let's see some examples:

Let's create five lists: 2 of them with mixed values, 2 with same values and one empty and then run the bool() function to check the Boolean value of them.

lst1 = [True, False, True]
lst2 = [False, True, False]
lst3 = [False, False, False]
lst4 = [True, True, True]
lst5 = []

print(bool(lst1), bool(lst2), bool(lst3), bool(lst4), bool(lst5))
>>>True True True True False

Enter fullscreen mode Exit fullscreen mode

We can see that all lists return True except the empty one!
Now let's understand how and and or work:

  • and: when using it, the operator will evaluate the first element of the comparison. If it's True than is returned the second element, if False than is returned the first element itself.
#all integers are considered True except zero
x = 1
y = 2
z = False

print(x and y)
>>> 2

print(y and x)
>>> 1

print(z and y)
>>> 

Enter fullscreen mode Exit fullscreen mode
  • or: when using it, the operator will first evaluate the first element of the comparison. If it's False than is returned the second element, if True than is returned the first element itself.
#all integers are considered True except zero
x = 1
y = 2
z = False

print(x and y)
>>> 1

print(y and x)
>>> 2

print(z and y)
>>> 2
Enter fullscreen mode Exit fullscreen mode

Now you can have an idea about what happened in the first code. The first list was evaluated and returned True, so the operation returned the second element (second list)!

You must be thinking right now, "Well, just False keyword and an empty string are considered False values in Python?"

Answer: NOOO!!!
According to the official reference are considered False values:

"False, None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets)"

The docs also tell us an example that this behavior can be useful:

"if s is a string that should be replaced by a default value if it is empty, the expression s or 'foo' yields the desired value. Because not has to create a new value, it returns a boolean value regardless of the type of its argument (for example, not 'foo' produces False rather than ''.)"

"What if I want to compare the pairs of elements by their positions?"

To do this, you can use & (and) and | (or) operators. These operators work bitwise:

lst1 = [False, True, False, True, True]
lst2 = [True, True, False, False, True]

print(lst1 & lst2)
>>> [False, True, False, False, True]

print(lst1 | lst2)
>>> [True, True, False, True, True]
Enter fullscreen mode Exit fullscreen mode

Hope these tips can be useful! See ya!

Top comments (0)