Track
In programming, we frequently need to make decisions based on multiple conditions. For instance, we might want to execute a certain action only if several conditions are met simultaneously. Alternatively, we might want to trigger an alternative action if any one of several conditions is fulfilled.
Python offers a set of logical operators – and
, or
, not
– to handle these scenarios.
In this tutorial, we'll learn how Python logical operators work and how to use them in programming and data science. Note that we’ll use the uppercase words AND, OR, and NOT to represent these operators conceptually. And we’ll refer to the Python keywords using this convention: and
, or
, and not
.
If you’re looking for a curated Python curriculum, check out this six-course Python Programming skill track.
Before getting into the details, let’s start with a very brief answer for those of you in a hurry.
Short Answer: What Are Python Logical Operators?
Python logical operators (and
, or
, not
) are special keywords that act as conjunctions in our code, connecting and evaluating multiple conditions within a single expression.
Consider this example:
temperature = 25
is_sunny = True
if temperature > 20 and is_sunny:
print("It's a perfect day for a picnic!")
It's a perfect day for a picnic!
Here, the and operator ensures that the message is printed only if both
conditions are met: the temperature is above 20 degrees and
it's sunny.
Let's look at another example using the or
operator:
has_umbrella = False
if is_sunny or has_umbrella:
print("Let's go for a walk!")
Let's go for a walk!
In this case, we'll head out for a walk if either it's sunny or we have an umbrella.
Finally, the not
operator flips the truth value of a condition:
if not is_sunny:
print("Maybe we should stay indoors.")
Here, the message is printed only if it is not sunny.
Logical operators give us a concise and powerful way to express complex conditions, allowing our programs to make decisions based on multiple factors. Now, let’s take a deeper look and start with the and
logical operator.
Python: The and
Operator
In Boolean logic, the AND operation involves comparing two values or expressions. It produces a true result only if both values are true. If either one or both of the values are false, the result of the AND operation is false. Here’s a summary of how AND behaves:
Operation |
Output value |
true AND true |
true |
true AND false |
false |
false AND true |
false |
false AND false |
false |
We can recreate this truth table with Python's and
operator:
options = True, False
for a in options:
for b in options:
print(f"{a} and {b} gives {a and b}")
True and True gives True
True and False gives False
False and True gives False
False and False gives False
The options
variable contains the two Boolean values. The nested for
loops iterate through options twice to create all permutations of True
and False
.
Often, the expressions used as operands for and include comparison or equality operators:
names = "James", "Bob", "David", "Jane", "Kate", "Mary"
for name in names:
if len(name) < 5 and name[0] == "J":
print(name)
Jane
The name is printed out only if it contains fewer than five letters and starts with "J"
. Both requirements must be met.
The comparison and equality operators, such as <
and ==
, evaluate to True
or False
.
However, the Python and
operator works on any data type and not just the Boolean True
and False
. The output value can also be any data type.
Let's explore Python's and
operator in more detail in this section. First, we'll discuss truthiness.
Python: truthy and falsy
Every Python object can be converted to a Boolean type using the built-in bool()
. An object is truthy if bool(object)
returns True
. For a falsy object, bool(object)
returns False
.
Python's and
operator looks at the truthiness of its operands. If both operands are truthy, the and
operator also returns a truthy value. If one or both operands are falsy, and
returns a falsy value. Let's look at some examples:
if 42 and "python":
print("Both operands are truthy")
else:
print("One or both operands are falsy")
Both operands are truthy
Now, let's consider this example:
if 42 and "":
print("Both operands are truthy")
else:
print("One or both operands are falsy")
One or both operands are falsy
And let's take a look at this final example:
if 0 and "python":
print("Both operands are truthy")
else:
print("One or both operands are falsy")
One or both operands are falsy
Numeric types, like integers and floats, are truthy if they're non-zero and falsy when equal to zero. Sequences, like strings, are truthy when they're non-empty and falsy when they're empty.
Therefore, only the first of the three examples above satisfies the condition that both operands should be truthy for the and
operator to evaluate to truthy.
The and
operator doesn't always return a Boolean value. An expression that includes and
could also evaluate to one of the operands. Let's dive into this further using the same examples we used earlier. Instead of using the and
expressions in an if
statement, we'll evaluate them directly:
print(42 and "python")
print(42 and "")
print(0 and "python")
python
0
Can you spot what's happening with these expressions?
Let's start with the last of the three examples, which has 0
and "python"
as the two operands. The and
operator is looking for two truthy operands. Since the first one is 0
, it's falsy. There's no need for the program to check the second operator since the whole expression will be falsy regardless of the value of the second operand.
However, the and
operator doesn't return False
. Instead, it returns the first operand directly. Since the first operand is falsy, the whole and
expression evaluates to falsy. This doesn't cause any issues in Python, as in situations where Python requires a true or false value, it can use the truthiness of an object.
In the first example, the first operand is 42
, which is truthy. The program evaluates the second operand and returns it. Since the second operand is the string "python"
, which is truthy, the whole expression evaluates as truthy.
In the second example, the first operand is also 42
. Since it's truthy, the program evaluates and returns the second operand, which is the empty string. The empty string is falsy, and therefore, the entire and
expression evaluates to falsy.
When the first operand is truthy, the and
operator always returns the value of the second operand, whether the second operand is truthy or falsy.
When the first operand is falsy, Python doesn't evaluate the second operand. This is called short-circuiting, and it's a form of lazy evaluation. You can confirm this with the following code:
0 and 5/0
0
The second operand is 5/0
, which would normally raise a ZeroDivisionError
. However, the 5/0
expression isn't evaluated in this example since the first operand is falsy. The exception is never raised.
Example: The Programmers' Online Store
Let's consider a simple example that represents a real-life application. Transactions in an online store that supplies goods for programmers are recorded and accessed through an API. The data are converted into a list of dictionaries. Each item in the list represents a transaction and each transaction is a dictionary containing relevant information:
data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]
Each transaction includes the item's name and price, the quantity included in the order, and whether the transaction was successful.
Let's assume we need successful transactions for items priced at $100 or over. We can use the and
operator to filter the rows we need:
for item in data:
if item["Success"] and item["Price"] >= 100:
print(item)
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}
The output from this code shows the only transaction that meets both requirements. For each item in the list of transactions, the if
statement checks the truthiness of two expressions:
- The values associated with the key
"Success"
in each dictionary are eitherTrue
orFalse
. - The greater than or equal to operator in
item["Price"] >= 100
also returnsTrue
orFalse
.
The Python book and the cables do not meet the price requirement as they're under $100. The coffee machine is over this price threshold, but this transaction wasn't successful, so it's excluded from the printout.
We'll return to this online store example later in this tutorial.
In the following section, we'll focus on the or
operator.
Python: The or
Operator
The OR logical operator in Boolean logic needs two operands. It evaluates to true if at least one of the operands is true:
Operation |
Output value |
true OR true |
true |
true OR false |
true |
false OR true |
true |
false OR false |
false |
We can recreate this truth table using Python's or
operator:
options = True, False
for a in options:
for b in options:
print(f"{a} or {b} gives {a or b}")
True or True gives True
True or False gives True
False or True gives True
False or False gives False
We can also revisit the example with people's names we explored earlier but replace the and
operator with an or
:
names = "James", "Bob", "David", "Jane", "Kate", "Mary"
for name in names:
if len(name) < 5 or name[0] == "J":
print(name)
James
Bob
Jane
Kate
Mary
The if
statement now contains an or
expression. Therefore, the for
loop prints all names that either have fewer than five letters or start with the letter "J"
. The string "Jane"
meets both requirements. The other printed names meet one of the two requirements.
Python or
operator: truthy and falsy
The or operator also looks for truthy and falsy values and not just the Booleans True
and False
. Let's look at some examples:
if 42 or [10, 20, 30]:
print("At least one operand is truthy")
else:
print("None of the operands is truthy")
At least one operand is truthy
Now let’s consider this example:
if 42 or []:
print("At least one operand is truthy")
else:
print("None of the operands is truthy")
At least one operand is truthy
And let’s also consider this final example:
if 0 or []:
print("At least one operand is truthy")
else:
print("None of the operands is truthy")
None of the operands is truthy
In the first example, the integer 42
and the non-empty list [10, 20, 30]
are truthy. Since the or
operator needs at least one operand to be truthy, the whole expression evaluates as truthy.
In the second example, 42
is truthy but the empty list []
is falsy since it's an empty sequence. As one of the two operands is truthy, the whole or expression evaluates as truthy.
In the final example, both 0
and []
are falsy. Therefore, the entire expression evaluates as falsy.
The or
operator also uses short-circuiting when evaluating the expression to avoid unnecessary evaluations. Let's look at some examples to illustrate this point:
print(42 or [10, 20, 30])
print(42 or [])
print([] or 42)
print([] or 0)
42
42
42
0
In the first example, the first operand is 42
, which is truthy. Since or
only requires one operand to be truthy to determine the final truthiness of the entire expression, this first operand is returned immediately. The second operand is not evaluated as its value has no effect on the final result. The or operator returns the first operand, 42
, not the Boolean True
. In Python, any truthy value has the same effect as the Boolean True
in situations such as if
statements and while statements.
In the second example, the first operand is also 42
, and the expression returns this integer even though the second operand is falsy.
In the third and fourth examples, the first operand is the empty list, which is falsy. Therefore, the second operand is returned in both cases.
Example: The Programmers' Online Store
Let's revisit the transactions from the online store that sells goods to programmers. Here are the four sample transactions we're using in this example:
data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]
You need to identify some transactions to investigate customer behavior further. You want to find the transactions that either failed or include an item priced below $75. Since you have two conditions and you only require a transaction to meet at least one of them, you can use the or
operator:
for item in data:
if item["Success"] == False or item["Price"] < 75:
print(item)
{'Item': 'Python Book', 'Price': 50, 'Quantity': 1, 'Success': True}
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
This for
loop displays the lines that match at least one of the requirements. The Python book and the cables are included as their price is below $75. The coffee machine is included since the transaction wasn't successful.
There's an alternative way of filtering the unsuccessful transactions, which we'll explore in the following section.
Python: The not
Operator
The NOT operator differs from AND and OR since it only requires one operand. NOT converts true to false and the other way round. Here's the truth table for NOT:
Operation |
Output value |
NOT true |
false |
NOT false |
true |
We can replicate this using Python's not
operator:
options = True, False
for a in options:
print(f"not {a} evaluates to {not a}")
not True evaluates to False
not False evaluates to True
Python not
operator: truthy and falsy
As with and
and or
, the operand used with not
doesn't have to be a Boolean. Since any object is either truthy or falsy, any object can be used with not
.
if not "python":
print("The `if` statement evaluated as `True`")
else:
print("The `if` statement evaluated as `False`")
The `if` statement evaluated as `False`
Let’s also look at this example:
if not "":
print("The `if` statement evaluated as `True`")
else:
print("The `if` statement evaluated as `False`")
The `if` statement evaluated as `True`
Truthy values are converted to False
with the not
operator and falsy values are converted to True
.
Unlike and
and or
, the not
operator always returns a Boolean object:
print(not "python")
print(not "")
False
True
Example: The Programmers' Online Store
In the previous sections, we used the transactions from an online store. We want to display all the unsuccessful transactions in this example. One option is using the equality operator ==
to check whether data["Success"]
equals False
. However, we can also use the not
operator instead:
data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]
for item in data:
if not item["Success"]:
print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
Since item["Success"]
is equal to False
for the unsuccessful transactions, not item["Success"]
returns True
. Therefore, the for loop prints out the unsuccessful transactions:
In the following section, we'll learn how to combine several logical operators in one expression.
Python: Operator Precendence
In the examples shown so far, we only used one of the logical operators in each instance. In this section, we'll see what happens when we combine more logical operators in a single expression.
Python: and
has precedence over or
We'll continue working on the transactions from the online store we used earlier. Let's try the following conditional statement:
data = [
{"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True},
{"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False},
{"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True},
{"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True},
]
for item in data:
if item["Price"] > 100 or item["Quantity"] > 2 and item["Success"]:
print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
The if
statement contains two logical operators. Before we investigate how Python deals with this expression, let's look at an English translation of the if
statement: If the item's price is over $100 or the quantity sold is greater than two and the sale was successful, then print the item.
This phrase is ambiguous without more punctuation marks and may still cause confusion even if we add more commas in the sentence. For example, should the transaction with the coffee machine be included? The item's price is over the required threshold but the transaction wasn't successful.
Python resolved this ambiguity by giving the and
operator precedence over the or
operator. This means that the and
expression is evaluated first, and its outcome is used in the or
expression.
Therefore, the expression item["Quantity"] > 2 and item["Success"]
is evaluated first. This expression returns a truthy value only for the transaction including cables. It evaluates as falsy for the remaining items.
The value from the and expression is then used with the or
operator. The or
expression returns a truthy value for any item that returns truthy for the and
expression—this was only the transaction including cables—and for items with a price over $100. There are two items with prices over the threshold: the coffee machine and the headphones.
Python: parentheses and logical operators
However, what if we need transactions with items priced above $100 or with a quantity above two, but we also want to ensure the transaction is successful? In this case, we want the or
expression to take precedence over the and
so that it's evaluated first. We can achieve this using parentheses around the or
expression:
for item in data:
if (item["Price"] > 100 or item["Quantity"] > 2) and item["Success"]:
print(item)
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
The additional parentheses give precedence to the or
expression. The coffee machine transaction is no longer included since it evaluates falsy for the second and
operand.
Python: not
has precedence over and
and or
The not
operator takes precedence over and
and or
. Therefore, not
is evaluated before the other two logical operators.
Let's consider the following if statement, which includes both not
and and
:
for item in data:
if not item["Success"] and item["Price"] > 100:
print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
Since not
is evaluated first, this expression will first apply the not operator to item["Success"]
. The value from the not
expression is then used as the first operand in the and expression. Only the coffee machine entry satisfies this condition—this is the only transaction that has failed and has a price over $100.
However, we can give precedence to the and
operator by using parentheses:
for item in data:
if not (item["Success"] and item["Price"] > 100):
print(item)
{'Item': 'Python Book', 'Price': 50, 'Quantity': 1, 'Success': True}
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
{'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
In this case, the and
expression is evaluated first. Only the entry with headphones evaluates to True
since it's the only successful transaction with a price over $100. However, we add a not
operator before the expression in parentheses. Therefore, the code outputs the remaining three transactions.
In general, if an expression becomes too complex because it has too many operators, it's best to split it to make it more readable.
Conclusion
The Python logical operators and
, or
, and not
are used extensively in a broad range of programming and data science applications. These operators replicate the behavior of the AND, OR, and NOT Boolean logical operators used broadly in logic and mathematics.
However, the Python operators can accept any object and not just Boolean values. The and
and or
operators use short-circuit evaluation and return one of the operands as their output.
The Python logical operators are key tools to filter data, identify features in data sets, and create complex rules to control the flow of a program. If you want to learn more about this, check out this nine-course Data Analyst With Python career track.
I studied Physics and Mathematics at UG level at the University of Malta. Then, I moved to London and got my PhD in Physics from Imperial College. I worked on novel optical techniques to image the human retina. Now, I focus on writing about Python, communicating about Python, and teaching Python.
Python Logical Operators FAQs
Can I use the and operator to test multiple conditions at once?
Yes, you can chain multiple conditions together using the and
operator. For example: if x > 5 and x < 10 and x != 7
.
What's the difference between the and operator and the bitwise AND operator (&)?
The and
operator performs a logical AND operation on Boolean values, returning True
only if both operands are True
. The bitwise AND operator (&
) performs a bitwise AND operation on the binary representation of integer values.
Does Python have the && and || operators like some other languages?
No, Python uses the keywords and
and or
instead of the symbols &&
and ||
for logical operations.
Learn more about Python and AI!
Track
AI Fundamentals
Course
Introduction to Data Literacy
tutorial
Operators in Python
tutorial
How to Use the Python 'Not Equal' Operator
tutorial
Operators in R
DataCamp Team
4 min
tutorial
Python IF, ELIF, and ELSE Statements
tutorial