Back to Blog
Python

Python Multiple Conditions in If Statements

python multiple conditions if: Learn how to combine multiple conditions in Python if statements using and, or, not, chained comparisons, and any()/all() with practical...

pythonif-statementsboolean-logicshort-circuit-evaluationconditional-expressions
Python if statement combining multiple boolean conditions with and and or operators in a code editor

When a single boolean expression isn't enough, Python's and, or, and not operators let you combine multiple conditions in one if statement. This is the core of python multiple conditions if logic: you build a compound boolean expression that evaluates to a single truth value before the branch runs.

temperature = 32 humidity = 75 if temperature > 30 and humidity > 60: print("Hot and humid")

and returns True only when both operands are truthy. or returns True when at least one operand is truthy. not inverts a single condition. These three operators are the building blocks for every compound condition in Python.

Combining Conditions with and, or, and not

The and and or operators accept any expression that can be evaluated for truthiness, not just boolean values. Strings, lists, dictionaries, and objects with __bool__ or __len__ all participate.

if user and user.email: print(user.email)

Here user is checked first. If it is None or otherwise falsy, the whole expression short-circuits and user.email is never accessed. This is a common pattern for guarding against AttributeError when a value may be missing.

or works the same way but stops at the first truthy operand:

display_name = user.nickname or user.full_name or "Anonymous"

This idiom picks the first non-empty value among several candidates.

Operator Precedence and Parentheses

Python evaluates not before and, and and before or. This precedence is easy to forget when a condition mixes all three operators.

if not user.is_admin and user.is_active: # Evaluated as: (not user.is_admin) and user.is_active

If the intent is to reject only active non-admins, this works. But if the intent is not (user.is_admin and user.is_active), the behavior is different: the second version rejects any admin, even an inactive one, and also rejects active non-admins.

Use parentheses whenever mixing operators. They cost nothing at runtime and remove ambiguity for the next developer who reads the code.

if (user.is_admin or user.is_moderator) and user.is_active: print("Privileged active user")

Without the parentheses, and binds tighter than or, so this would evaluate as user.is_admin or (user.is_moderator and user.is_active), which grants admin access even to inactive users.

Chained Comparisons for Ranges

Python's chained comparison syntax is a compact way to express a range check in a single expression.

if 18 <= age < 65: print("Working age")

This is equivalent to age >= 18 and age < 65, but it evaluates age only once and reads more naturally. Chained comparisons work with any comparison operators, including ==, !=, <, >, <=, and >=:

if start < current < end: print("Within interval")

This is particularly useful for validating numeric input, time ranges, or index bounds.

Using any() and all() for Dynamic Conditions

When the number of conditions is not known at write time, or when conditions come from a list, generator, or user input, any() and all() are the right tools.

required_fields = ["name", "email", "phone"] missing = [field for field in required_fields if not form.get(field)] if any(missing): print(f"Missing: {', '.join(missing)}")

any() returns True if at least one element is truthy. all() returns True if every element is truthy. Both short-circuit: any() stops at the first truthy value, and all() stops at the first falsy value.

This pattern is cleaner than generating a long or chain dynamically, which would require functools.reduce or eval and is harder to debug.

Short-Circuit Evaluation and Runtime Cost

Python evaluates and and or lazily from left to right. The right operand is evaluated only when the left operand does not already determine the result. This has two practical consequences.

First, you can guard expensive or unsafe operations behind a cheap check:

if user is not None and user.is_active and user.has_permission("export"): export_data(user)

If user is None, the remaining checks never run, so no AttributeError occurs.

Second, ordering conditions by cost and likelihood improves average-case runtime. Put the cheapest or most selective check first. For example, checking a string length before running a regular expression avoids the regex work for most inputs:

if len(code) == 10 and re.fullmatch(pattern, code): process(code)

This is a mechanism-level improvement, not a measured benchmark claim: fewer operations execute on average because the cheaper check filters out most inputs first.

Common Mistakes with Bitwise Operators

A frequent error is using & and | instead of and and or. These are bitwise operators with different semantics and much higher precedence.

if flags & ENABLED: # bitwise AND if a | b: # bitwise OR

With boolean operands, & and | often produce the same result as and and or, which makes the bug easy to miss. The difference appears with non-boolean operands. 1 and 2 evaluates to 2 (the last truthy operand), while 1 & 2 evaluates to 0 (the bitwise result). This can silently change control flow.

Also note that & binds tighter than comparison operators, so a & b == c parses as a & (b == c), which is rarely what you want. Stick to and and or for logical conditions.

Keeping Complex Conditions Readable

When a condition grows beyond two or three checks, inline boolean expressions become hard to read and hard to test. Extract the condition into a named variable or a small helper function.

def is_eligible(user, order): return ( user.is_active and not user.is_blacklisted and order.total >= 100 and order.payment_status == "paid" ) if is_eligible(user, order): process(order)

The helper function gives the condition a name, makes the logic testable in isolation, and keeps the calling site readable. It also makes it easier to change the eligibility rules later without touching every call site.

For one-off scripts, a single named variable is often enough:

is_priority = user.is_subscriber and order.total >= 500 if is_priority: apply_priority_shipping(order)

The variable name documents the intent, and the condition remains local to the function.

python multiple conditions if: Practical Usage and Code Exam | RYUSLOG DEV