OR and AND in Python

Logical operators in Python is not just “logical”. You will have powerful tool If you understand it’s mechanics. In Python operators AND and OR doesn’t return boolean value. It always return one of the operand. So you can use logical operators not only in if/else statement. For example:

print(1 or 2). # return 1

How it works?

OR operator

In case of OR returned first value evaluated as True. If there is no True values, it returned last operand. This behavior very useful if you need to return value by default when evaluated value is False or None or zero:

count_items = count(items) or 'No items'

Another example if some evaluated code return value or False, but you need None instead of False. You can write:

count_items = count(items) or None

In this case if count(items) return False, count_items will be None. Remember? If all of the operands are False, OR returns last operand.

In next example OR looks like dummy plug, but it works perfect and very clean:

avg_salary = sum_salary / (count_emplyers or 1)

This code is for case when we iterate through some array of departments and calculate average salary of each department. And one department doesn’t have any employers and salaries. Without OR we will receive ZeroDivisionError exception. But we add just OR 1 and everything works. avg_salary now is 0.

But why we add round brackets? It’s because logic operators has lowest priority and we need to evaluate (count_emplyers or 1) statement at first.

AND operator

In case of AND, conversely, returned first value evaluated as False. If there is no False values, it returned last operand (if it even False). AND operator in this behavior is using quite rarely. Here is classic example:

def digital_root(num):
	return num % 9 or num and 9

WTF? Okay, okay, maybe it’s not a classic :) This func calculates digital root of a number . Expression num % 9 almost always return right answer. Almost, because in one case is not: if num don’t have remainder with division on 9. But digital root of any number which divided without remainder on 9 is.. 9! So, we should return 9 if there is no remainder:

return num % 9 or 9

Right? Right! Or no? No! We forget about zero! If number is 0 we should return 0, not 9. In this case OR plays a cruel joke. And now AND takes the stage. AND have priority and evaluates first. Expression num and 9 return 0 if num is 0. So, we cover num = 0 case with AND operator.

AND and OR are lazy

What does that mean? OR don’t execute next values if it found truthly value before. And similarly AND operator don’t execute next values if it found False before. It is useful in many cases, like this:

some_list = ['one']
if some_list and some_list[0] == 'one':  # if some_list == [] there is no list index out of range error
	pass

AND and OR operators are really powerful. But do not get carried away with it. Simple and easy-to-read code is more important than shortness.