Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Using the Python or Operator
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.
Free Download: Get a sample chapter from Python Tricks: The Book that shows you Python’s best practices with simple examples you can apply instantly to write more beautiful + Pythonic 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
orFalse
. In Python, the Boolean type isbool
, which is a subtype ofint
. -
Boolean values are the values
True
orFalse
(with a capital T and F) in Python. -
A Boolean variable is a variable that can be either
True
orFalse
. Boolean variables are commonly used asflags
to indicate whether specific conditions exist. -
A Boolean expression is an expression that returns either
True
orFalse
. -
Boolean context can be
if
conditions andwhile
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
(logicalAND
or conjunction),OR
(logicalOR
or disjunction), andNOT
(logicalNOT
or negation). The keywordsand
,or
, andnot
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:
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 returnsFalse
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
andFalse
.- 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.
Note: If you really need to get one of the values True
or False
from a Boolean expression involving objects, then you could use bool(obj)
, which is a built-in function that returns True
or False
depending on the truth value of obj
.
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
orFalse
values when it tests Python objects. This means that the expressionx or y
returnsx
if it’s evaluated to true, and otherwise returnsy
(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:
if
statements: conditional executionwhile
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)
.
Note: In the previous code example, you used Python’s f-strings for string formatting, if you want to dive deeper into f-strings, then you can take a look at Python’s F-String for String Interpolation and Formatting.
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.
Note: In the previous code example, you saw how Python raises exceptions when some problems occur. If you want to know more about exceptions in Python, then you can take a look Introduction to Python Exceptions.
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.
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Using the Python or Operator