How to Use the Python or Operator

How to Use the Python or Operator

by Leodanis Pozo Ramos Jul 03, 2019 basics python
Tweet Share Email

There are three Boolean operators in Python: and, or, and not. With them, you can test conditions and decide which execution path your programs will take. In this tutorial, you’ll learn about the Python or operator and how to use it.

By the end of this tutorial, you’ll have learned:

  • How the Python or operator works

  • How to use the Python or operator in Boolean and non-Boolean contexts

  • What kind of programming problems you can solve by using or in Python

  • How to read and better understand other people’s code when they use some of the special features of the Python or operator

You’ll learn how to use the Python or operator by building some practical examples. Even if you don’t really use all the possibilities that the Python or operator offers, mastering it will allow you to write better code.

Boolean Logic

George Boole (1815–1864) developed what is now called Boolean algebra, which is the foundation of the digital logic behind computer hardware and programming languages.

Boolean algebra is built around the truth value of expressions and objects (whether they are true or false) and is based in the Boolean operations AND, OR, and NOT. These operations are implemented through logical or Boolean operators that allow you to create Boolean expressions, which are expressions that evaluate to true or false.

With the help of Boolean logic, you can evaluate conditions and decide what operations your programs will execute, depending on the truth value of those conditions. This is an important cornerstone in programming and provides you with the tools to decide the execution flow of your programs.

Let’s take a look at some of the basic concepts related to Boolean logic in Python:

  • Boolean is type of value that can be either True or False. In Python, the Boolean type is bool, which is a subtype of int.

  • Boolean values are the values True or False (with a capital T and F) in Python.

  • A Boolean variable is a variable that can be either True or False. Boolean variables are commonly used as flags to indicate whether specific conditions exist.

  • A Boolean expression is an expression that returns either True or False.

  • Boolean context can be if conditions and while loops, where Python expects an expression to evaluate to a Boolean value. You can use virtually any expression or object in a Boolean context, and Python will try to determine its truth value.

  • Operands are the subexpressions or objects involved in an expression (Boolean or not) and connected by an operator.

  • Boolean or logical operators are AND (logical AND or conjunction), OR (logical OR or disjunction), and NOT (logical NOT or negation). The keywords and, or, and not are the Python operators for these operations.

Now that you have a better context on Boolean logic, let’s proceed with some more Python-specific topics.

The Python Boolean Operators

Python has three Boolean operators that are typed out as plain English words:

  1. and
  2. or
  3. not

These operators connect Boolean expressions (and objects) to create compound Boolean expressions.

The Python Boolean operators always take two Boolean expressions or two objects or a combination of them, so they’re considered binary operators.

In this tutorial, you’ll be covering the Python or operator, which is the operator that implements the logical OR operation in Python. You’ll learn how it works and how to use it.

How the Python or Operator Works

With the Boolean OR operator, you can connect two Boolean expressions into one compound expression. At least one subexpressions must be true for the compound expression to be considered true, and it doesn’t matter which. If both subexpressions are false, then the expression is false.

This is the general logic behind the OR operator. However, the Python or operator does all this and more, as you’ll see in the following sections.

Using or With Boolean Expressions

You’ll need two subexpressions to create a Boolean expression using the Python or operator as a connector. The basic syntax for a Boolean expression with or is as follows:

# Syntax for Boolean expression with or in Python
exp1 or exp2

If at least one of the subexpressions (exp1 or exp2) evaluates to True, then the expression is considered to be True. If both subexpressions evaluate to False, then the expression is False. This definition is called inclusive or, since it allows both possibilities as well as either.

Here’s a summary of the Python or operator’s behavior:

Result of exp1 Result of exp2 Result of exp1 or exp2
True True True
True False True
False True True
False False False

Table 1. Logical Python or Operator: Truth Table

This table summarizes the resulting truth value of a Boolean expression like exp1 or exp2 depending on the truth values of its subexpressions.

Let’s illustrate the resulting truth values shown in Table 1 by coding some practical examples:

>>>
>>> exp1 = 1 == 2
>>> exp1
False
>>> exp2 = 7 > 3
>>> exp2
True
>>> exp1 or exp2  # Return True, because exp2 is True
True
>>> exp2 or exp1  # Also returns True
True
>>> exp3 = 3 < 1
>>> exp1 or exp3  # Return False, because both are False
False

In the previous examples, whenever a subexpression is evaluated to True, the global result is True. On the other hand, if both subexpressions are evaluated to False, then the global result is also False.

Using or With Common Objects

In general, the operands of an expression involving an OR operation should have Boolean values as shown in Table 1 and return a truth value as a result. When it comes to objects, Python is not very strict about that and internally implements a set of rules to decide if an object is considered true or false:

By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero, when called with the object. Here are most of the built-in objects considered false:

  • constants defined to be false: None and False.
  • zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • empty sequences and collections: '', (), [], {}, set(), range(0)

(Source)

If the operands involved in an or operation are objects instead of Boolean expressions, then the Python or operator returns a true or false object, not the values True or False as you could expect. The truth value of this object is determined according to the rules you’ve seen before.

This means that Python doesn’t coerce the result of an or operation to a bool object. If you’re testing two objects using or in Python, then the operator will return the first object that evaluates to true or the last object in the expression, regardless of its truth value:

>>>
>>> 2 or 3
2
>>> 5 or 0.0
5
>>> [] or 3
3
>>> 0 or {}
{}

In the two first examples, the first operands (2 and 5) are true (nonzero), so the Python or operator always returns the first one.

In the last two examples, the left operand is false (an empty object). The Python or operator evaluates both operands and returns the object on the right, which may evaluate to either true or false.

You can summarize the behavior shown in the previous code as follows:

Left Object Right Object Result of x or y
x y x, if it evaluates to true, otherwise y.

Table 2. Python or Operator Behavior When Testing Objects Instead of Boolean Expressions

In short, the Python or operator returns the first object that evaluates to true or the last object in the expression, regardless of its truth value.

You can generalize this behavior by chaining several operations in a single expression like this:

a or b or c or d

In this example, the Python or operator returns the first true operand it finds, or the last one. This is the rule of thumb to memorize how or works in Python.

Mixing Boolean Expressions and Objects

You can also combine Boolean expressions and common Python objects in an or operation. In this case, the Python or operator will still return the first true operand or the last operand, but the returned value could be True or False or the object you’re testing:

Result of Expression Result of Object Result of exp or obj
True True True
True False True
False False obj
False True obj

Table 3. Python or Operator Behavior When Testing Objects and Boolean Expressions

Let’s see how this works with some examples:

>>>
>>> 2 < 4 or 2  # Case 1
True
>>> 2 < 4 or []  # Case 2
True
>>> 5 > 10 or []  # Case 3
[]
>>> 5 > 10 or 4  # Case 4
4

In Case 1 and Case 2, the subexpression 2 < 4 was evaluated to True, and the returned value was True. On the other hand, in Case 3 and Case 4, the subexpression 5 > 10 was evaluated to False, so the last operand was returned, and you got an empty list ([]) and an integer (4) instead of True or False.

As an exercise, you could try to extend Table 3 by reversing the order of the expressions in the third column, that is, use obj or exp and try to predict the results.

Short-Circuit Evaluation

Python can sometimes determine the truth value of a Boolean expression before it has evaluated all the subexpressions and objects involved. The Python or operator, for instance, stops evaluating operands as soon as it finds something that’s considered true. For example, the following expression is always True:

>>>
>>> True or 4 < 3
True

If the first operand in an or expression evaluates to true, regardless of the value of the second operand (4 < 3 is False), then the expression is considered to be true, and the second operand is never evaluated. This is called short-circuit (lazy) evaluation.

Let’s consider another example:

>>>
>>> def true_func():
...     print('Running true_func()')
...     return True
...
>>> def false_func():
...     print('Running false_func()')
...     return False
...
>>> true_func() or false_func()  # Case 1
Running true_func()
True
>>> false_func() or true_func()  # Case 2
Running false_func()
Running true_func()
True
>>> false_func() or false_func()  # Case 3
Running false_func()
Running false_func()
False
>>> true_func() or true_func()  # Case 4
Running true_func()
True

In Case 1, Python evaluated true_func(). Since it returns True, the next operand (false_func()) is not evaluated. Notice that the phrase Running false_func() is never printed. Finally, the whole expression is considered True.

Case 2 evaluates both functions, because the first operand (false_func()) is False. Then the operator returns the second result, that is, the value returned by true_func(), which is True.

Case 3 evaluates both functions, because both return False. The operation returns the last function’s return value, that is False, and the expression is considered to be False.

In Case 4, Python only evaluates the first function, which is True, and the expression is True.

In short-circuit (lazy) evaluation, the second operand on a Boolean expression is not evaluated if the value of the expression can be determined from the first operand alone. Python (like other languages) bypasses this second evaluation in favor of performance, because evaluating the second operand would be an unnecessary waste of CPU time.

Finally, when it comes to performance when you’re using the Python or operator, consider the follow:

  • The expressions on the right side of the Python or operator might call functions that perform substantial or important work, or have side effects that won’t happen if the short-circuit rule takes effect.

  • The condition that is more likely to be true might be the left-most condition. This approach can reduce the execution time of your programs, because this way Python is able to determine if the condition is true just by evaluating the first operand.

Section Recap

You’ve learned how the Python or operator works and have seen some of its main features and behaviors. You now know enough to continue leveling up by learning how to use the operator in solving real-world problems.

Before that, let’s recap some important points about or in Python:

  • It satisfies the general rules that a Boolean OR operator should follow. If one or both Boolean subexpression are true, then the result is true. Otherwise, if both subexpressions are false, then the result is false.

  • It returns objects instead of True or False values when it tests Python objects. This means that the expression x or y returns x if it’s evaluated to true, and otherwise returns y (regardless of its truth value).

  • It follows a predefined set of Python internal rules to determine the truth value of an object.

  • It stops evaluating operands as soon as it finds something that’s considered true. This is called short-circuit or lazy evaluation.

Now it’s time to learn where and how you can use this operator with the help of some examples.

Boolean Contexts

In this section, you’ll see some practical examples of how to use the Python or operator, and learn how to take advantage of its somewhat unusual behavior to write better Python code.

There are two main situations where you can say you’re working in a Boolean context in Python:

  1. if statements: conditional execution
  2. while loops: conditional repetition

With an if statement, you can decide your programs’ path of execution depending on the truth value of some conditions.

On the other hand, while loops allow you to repeat a piece of code as long as a given condition remains true.

These two structures are part of what you’d call control flow statements. They help you decide your programs’ execution path.

You can use the Python or operator to build Boolean expressions suitable for use with both if statement and while loops, as you’ll see in the next two sections.

if Statements

Let’s say you want to make sure that one of two conditions (or both) is true before you choose a certain path of execution. In this case, you can use the Python or operator to connect the conditions in one expression, and use that expression in an if statement.

Suppose you need to get a confirmation from the user to run some actions depending on the user’s answer:

>>>
>>> def answer():
...     ans = input('Do you...? (yes/no): ')
...     if ans.lower() == 'yes' or ans.lower() == 'y':
...         print(f'Positive answer: {ans}')
...     elif ans.lower() == 'no' or ans.lower() == 'n':
...         print(f'Negative answer: {ans}')
...
>>> answer()
Do you...? (yes/no): y
Positive answer: y
>>> answer()
Do you...? (yes/no): n
Negative answer: n

Here, you get the user’s input and assign it to ans. Then, the if statement starts checking the conditions from left to right. If at least one of them is evaluated to true, then it executes the if code block. The elif statement does the same.

In the first call to answer(), the user’s input was y, which satisfied the first condition, and the if code block was executed. In the second call, the user’s input (n) satisfied the second condition, so the elif code block ran. If the user input doesn’t satisfy any condition, then no code block is executed.

Another example could be when you’re trying to determine whether a number is outside a range. In this case, it’s also possible to use the Python or operator. The following code tests whether x is outside the range of 20 through 40:

>>>
>>> def my_range(x):
...     if x < 20 or x > 40:
...         print('Outside')
...     else:
...         print('Inside')
...
>>> my_range(25)
Inside
>>> my_range(18)
Outside

When you call my_range() with x=25, the if statement tests 25 < 20, which is False. Then it tests x > 40, which is also False. The final result is False, so the else block was executed.

On the other hand, 18 < 20 is evaluated to True. Then the Python or operator makes short-circuit evaluation, and the condition is considered to be True. The main block is executed, and the value is outside the range.

while Loops

while loops are another example of Boolean context where you can use the Python or operator. By using or in the loop’s header, you can test several conditions and run the body until all the conditions evaluate to false.

Suppose you need to measure the operating temperature of some industrial equipment until it gets into a range of 100 ºF to 140 ºF. To do so, you can use a while loop:

from time import sleep

temp = measure_temp()  # Initial temperature measurement

while temp < 100 or temp > 140:
    print('Temperature outside the recommended range')
    print('New Temperature measure in 30 seconds')
    sleep(30)
    print('Measuring Temperature...')
    temp = measure_temp()
    print(f'The new Temperature is {temp} ºF')

This is a toy example almost in pseudo code, but it illustrates the idea. Here, the while loop is running until temp is between 100 ºF and 140 ºF. If the temperature value is outside the range, then the loop’s body is run, and you’ll be measuring the temperature again. Once measure_temp() returns a value between 100 ºF and 140 ºF, the loop finishes. The temperature measurement is taken every 30 seconds by using sleep(30).

Non-Boolean Contexts

You can take advantage of the special features of the Python or operator out of Boolean contexts. The rule of thumb is still that the result of your Boolean expressions is the first true operand or the last in the line.

Notice that the logical operators (or included) are evaluated before the assignment operator (=), so you can assign the result of a Boolean expression to a variable in the same way you do with a common expression:

>>>
>>> a = 1
>>> b = 2
>>> var1 = a or b
>>> var1
1
>>> a = None
>>> b = 2
>>> var2 = a or b
>>> var2
2
>>> a = []
>>> b = {}
>>> var3 = a or b
>>> var3
{}

Here, the or operator works as expected, returning the first true operand or the last operand if both are evaluated to false.

You can take advantage of this somewhat special behavior of or in Python to implement a Pythonic solution to some quite common programming problems. Let’s take a look at some real-world examples.

Default Values for Variables

One common way to use the Python or operator is to select an object from a set of objects according to its truth value. You can do this by using an assignment statement:

>>>
>>> x = a or b or None

Here, you assigned to x the first true object in the expression. If all objects (a and b in this case) are false objects, then the Python or operator returns None, which is the last operand. This works because the or operator returns one of its operands depending on their truth value.

You can also use this feature to assign a default value to your variables. The following example sets x to a if a is true, and to default otherwise:

>>>
>>> x = a or default

In the previous code, you assign a to x only if a is evaluated to true. Otherwise, x is assigned default.

Default return Values

You can manipulate the return value of some built-in functions at call time. Functions like max() and min(), which take an iterable as an argument and return a single value, could be your perfect candidate for this sort of hack.

If you supply an empty iterable to max() or min(), then you’ll get a ValueError. However, you can modify this behavior by using the Python or operator. Let’s take a look at the following code:

>>>
>>> lst = []  # Empty list to test max() and min()
>>> max(lst)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    max(lst)
ValueError: max() arg is an empty sequence
>>> min(lst)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    min(lst)
ValueError: min() arg is an empty sequence
>>> # Use Python or operator to modify this behavior
>>> max(lst or [0])  # Return 0
0
>>> min(lst or [0])  # Return 0
0

The default behavior of max() and min() is to raise a ValueError if you call them with an empty iterable. However, by using the Python or operator, you supply a default return value for these functions and override their default behavior.

Mutable Default Arguments

A common problem beginner Python programmers face is to try to use mutable objects as default arguments to functions.

Mutable values for default arguments can retain state between calls. This is often unexpected. It happens because default argument values are evaluated and saved only once, that is, when the def statement is run, not each time the resulting function is called. That’s why you need to be careful about changing mutable defaults inside functions.

Consider the following example:

>>>
>>> def mutable_default(lst=[]):  # Try to use a mutable value as default
...     lst.append(1)  # Change same object each time
...     print(lst)
...
>>> mutable_default(lst=[3, 2])  # Default not used
[3, 2, 1]
>>> mutable_default()  # Default used
[1]
>>> mutable_default()  # Default grows on each call
[1, 1]
>>> mutable_default()
[1, 1, 1]

Here, every call to mutable_default() appends 1 to the end of lst, because lst holds a reference to the same object (the default []). You don’t get a new list every time the function is called as you would expect.

If that’s not the behavior you want, then the traditional (and safest) solution is to move the default to the body of the function:

>>>
>>> def mutable_default(lst=None):  # Use None as formal default
...     if lst is None:
...         lst = []  # Default used? Then lst gets a new empty list.
...     lst.append(1)
...     print(lst)
...
>>> mutable_default(lst=[3, 2])  # Default not used
[3, 2, 1]
>>> mutable_default()  # Default used
[1]
>>> mutable_default()
[1]

With this implementation, you are ensuring that lst is set to an empty list every time you call mutable_default() with no argument, relying in the default value for lst.

The if statement in this example could almost be replaced by the assignment lst = lst or []. This way, if no argument is passed in to the function, then lst would default to None and the Python or operator would return the empty list on the right:

>>>
>>> def mutable_default(lst=None):  # Use None as formal default
...     lst = lst or []  # Default used? Then lst gets an empty list.
...     lst.append(1)
...     print(lst)
...
>>> mutable_default(lst=[3, 2])  # Default not used
[3, 2, 1]
>>> mutable_default()  # Default used
[1]
>>> mutable_default()
[1]

However, this isn’t exactly the same. For example, if an empty list is passed in, then the or operation would cause the function to modify and print a newly created list, rather than modifying and printing the originally passed-in list like the if version would do.

If you are pretty sure that you’ll only be using non-empty list objects, then you can use this approach. Otherwise, stick to the if version.

Zero Division

Zero division can be a common problem when you’re dealing with numeric calculations. To avoid this problem, it’s likely that you end up checking if the denominator is equal to 0 or not by using an if statement.

Let’s take a look at an example:

>>>
>>> def divide(a, b):
...     if not b == 0:
...         return a / b
...
>>> divide(15, 3)
5.0
>>> divide(0, 3)
0.0
>>> divide(15, 0)

Here, you tested if the denominator (b) was not equal to 0, and then you returned the result of the division operation. If b == 0 is evaluated to True, then divide() implicitly returns None. Let’s see how to get a similar result, but this time using the Python or operator:

>>>
>>> def divide(a, b):
...     return b == 0 or a / b
...
>>> divide(15, 3)
5.0
>>> divide(0, 3)
0.0
>>> divide(15, 0)
True

In this case, the Python or operator evaluates the first subexpression (b == 0). Only if this subexpression is False, the second subexpression (a / b) is evaluated, and the final result will be the division of a and b.

The difference with the previous example is that, if b == 0 is evaluated to True, then divide() returns True instead of the implicit None.

Multiple Expressions in lambda

Python provides lambda expressions, which allow you to create simple anonymous functions. The expression lambda parameters: expression yields a function object. This kind of function may be useful if you want to define simple callback and key functions.

The most common pattern for you to write a lambda function is to use a single expression as a return value. However, you can change this and let lambda execute several expressions by using the Python or operator:

>>>
>>> lambda_func = lambda hello, world: print(hello, end=' ') or print(world)
>>> lambda_func('Hello', 'World!')
Hello World!

With this example, you’ve forced lambda to run two expressions (print(hello, end=' ') and print(world)). But how does this code work? Well, here lambda runs a Boolean expression where two functions are executed.

When or evaluates the first function, it receives None, which is the implicit return value for print(). Since None is considered to be false, or continues to evaluate its second operand, and finally returns it as a result for the Boolean expression.

In this case, the value returned by the Boolean expression is also the value returned by lambda:

>>>
>>> result = lambda_func('Hello', 'World!')
Hello World!
>>> print(result)
None

Here, result holds a reference to the value returned by lambda, which is the same value returned by the Boolean expression.

Conclusion

You now know how the Python or operator works as well as how to use it for solving some common programming problems in Python.

Now that you know the basics of the Python or operator, you’ll be able to:

  • Use the Python or operator in Boolean and non-Boolean contexts

  • Solve several kind of programming problems by effectively using the Python or operator

  • Write better and more Pythonic code by taking advantage of the somewhat special features of or in Python

  • Read and better understand other people’s code when they make use of the Python or operator

In addition, you’ve learned a little bit about Boolean logic, as well as some of its main concepts in Python.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Leodanis Pozo Ramos

Leodanis Pozo Ramos

Leodanis is an industrial engineer who loves Python and software development. He is a self-taught Python programmer with 5+ years of experience building desktop applications.

» More about Leodanis

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

What Do You Think?

Real Python Comment Policy: The most useful comments are those written with the goal of learning from or helping out other readers—after reading the whole article and all the earlier comments. Complaints and insults generally won’t make the cut here.

Keep Learning

Related Tutorial Categories: basics python