Python online course

Python Logical Operators: and, or, and not

Learn how Python's and, or, and not logical operators combine Boolean conditions in if, elif, and else statements, including ranges, precedence, and short-circuiting.

What logical operators do

A Boolean is a value that is either True or False. A condition is an expression that Python evaluates to decide whether code should run. For example, age > 18 produces a Boolean result.

A logical operator combines Boolean conditions or reverses one. Python provides three logical operators:

  • and is true only when all connected conditions are true.
  • or is true when at least one connected condition is true.
  • not reverses a Boolean result.

Logical expressions are commonly used in conditional statements with if, elif, and else.

age = 25

if age >= 18:
    print("Adult")
else:
    print("Under 18")

In this example, age >= 18 is the condition. Its result is True for an age of 25, so the if branch runs.

The and operator

Use and when every requirement must be satisfied. An expression using and is true only when every connected condition is true.

age = 35

if age >= 21 and age <= 100:
    print("Age is in the acceptable range")

Both comparisons must be true: the age must be at least 21 and no more than 100. This makes and suitable for a value that must meet multiple requirements simultaneously.

A truth table shows the result for possible Boolean inputs:

A | B | A and B | A or B | not A True | True | True | True | False True | False | False | True | False False | True | False | True | True False | False | False | False | True

Checking an acceptable range

For inclusive endpoints, use >= and <=. The following accepts every integer from 21 through 100:

minimum = 21
maximum = 100
age = 60

if minimum <= age and age <= maximum:
    print("Accepted")

The or operator

Use or when alternatives are acceptable. An expression using or is true when either condition, or both conditions, are true.

age = 15

if age < 21 or age > 100:
    print("Age is outside the acceptable range")
else:
    print("Age is acceptable")

This is an invalid-range test. The value is rejected if it is below the minimum or above the maximum. or is also useful when different conditions can independently cause an action.

has_coupon = False
is_member = True

if is_member or has_coupon:
    print("Discount available")

The not operator

not reverses a Boolean value: not True is False, and not False is True.

logged_in = False

if not logged_in:
    print("Please log in")

You can also negate a comparison. Parentheses make the expression easier to read:

age = 20

if not (age >= 21):
    print("Not old enough")

A direct positive condition is sometimes clearer. Instead of if not (age >= 21), use if age < 21 when that describes the intended rule more naturally. Negation is especially useful with flags such as not logged_in or not account_suspended.

Using logical expressions with if, elif, and else

Python evaluates an if condition first. If it is false, Python checks each elif condition in order. The first true branch runs, and later elif branches are skipped. The else branch runs only when no earlier condition is true.

age = int(input("Enter your age: "))

if 0 <= age <= 12:
    print("Child")
elif 13 <= age <= 20:
    print("Young adult")
elif 21 <= age <= 59:
    print("Adult")
elif 60 <= age <= 100:
    print("Senior")
else:
    print("Implausible age")

The ranges are ordered, non-overlapping, and inclusive. For example, 12 is a child, 13 is a young adult, 21 is an adult, and 60 is a senior.

Age range test cases

Input age | Condition result | Selected branch | Expected message 0 | True for 0 <= age <= 12 | first if | Child 12 | True for 0 <= age <= 12 | first if | Child 21 | True for 21 <= age <= 59 | second elif after earlier tests fail | Adult 40 | True for 21 <= age <= 59 | adult elif | Adult 60 | True for 60 <= age <= 100 | senior elif | Senior 100 | True for 60 <= age <= 100 | senior elif | Senior 101 | All range tests false | else | Implausible age

Inclusive and exclusive range boundaries

Comparison operators determine whether endpoints belong to a range:

  • > means greater than, excluding the value on the right.
  • >= means greater than or equal to, including the value on the right.
  • < means less than, excluding the value on the right.
  • <= means less than or equal to, including the value on the right.

This condition excludes both endpoints:

if age > 0 and age < 21:
    print("Age is between 1 and 20")

To include 0 and 21, write 0 <= age and age <= 21. Be deliberate when selecting boundary operators.

Gaps between adjacent ranges

Consider these conditions:

if age > 0 and age < 21:
    print("First group")
elif age > 21 and age < 40:
    print("Second group")
else:
    print("Fallback")

The value 21 is not included in either range, so it reaches else. The first range excludes 21, and the second range also excludes 21. Use inclusive boundaries or explicitly assign the boundary to one group.

Chained comparisons

Python lets you write several comparisons in a chain:

if 21 <= age <= 100:
    print("Accepted")

This means the same thing as:

if age >= 21 and age <= 100:
    print("Accepted")

A chained comparison is concise and often makes a range check easier to read. It should not be confused with the invalid expression age > 0 and < 21; each separate comparison must include its value, unless you use valid chained syntax such as 0 < age < 21.

Operator precedence and parentheses

Operator precedence determines the order in which Python evaluates parts of an expression. For these operators, the relevant order from higher to lower priority is:

Priority | Operator category | Examples 1 | Comparisons | <, >=, ==, != 2 | not | not logged_in 3 | and | is_member and paid 4 | or | is_member or has_coupon

Comparisons are evaluated before not, then and, then or. Therefore:

eligible = is_member and purchase >= 100 or has_coupon

is interpreted as:

eligible = (is_member and purchase >= 100) or has_coupon

Parentheses are recommended when they clarify the intended groups:

if is_member and (purchase >= 100 or has_coupon):
    print("Discount approved")

These two expressions have different meanings. In the first, a coupon alone can qualify a customer. In the second, membership is always required.

Short-circuit evaluation

Short-circuit evaluation means Python stops evaluating a logical expression as soon as its final result is known.

  • With and, a false operand makes the whole expression false, so later operands are skipped.
  • With or, a true operand makes the whole expression true, so later operands are skipped.

This behavior is useful for safe checks. Put the guard first:

value = None

if value is not None and value > 0:
    print("Positive value")

Because value is not None is false, Python does not evaluate value > 0. This prevents a comparison error. Ordering conditions this way can also avoid unnecessary work.

Common conditional logic mistakes

Leaving out the value in a comparison

This is invalid Python syntax:

if age > 0 and < 21:
    print("Valid")

Write either a complete pair of comparisons or a chained comparison:

if age > 0 and age < 21:
    print("Valid")

if 0 < age < 21:
    print("Valid")

Misusing or for multiple exact values

This does not test whether age equals 18 or 21:

if age == 18 or 21:
    print("Special age")

The literal 21 is treated as a truthy value, so the condition behaves incorrectly. Compare the variable each time:

if age == 18 or age == 21:
    print("Special age")

For several choices, membership testing is often clearer:

if age in (18, 21):
    print("Special age")

Confusing assignment and equality

= assigns a value, while == tests whether two values are equal:

age = 21          # assignment
is_twenty_one = age == 21  # comparison

Use == in a condition.

Creating overlapping or unreachable ranges

Overlapping ranges can make later branches unreachable because an earlier condition catches the value first. Incomplete ranges can also send valid inputs to else. Define each endpoint deliberately, keep ranges non-overlapping, and remember that Python selects only the first true branch.

Assuming all input is numeric

input() returns text, and int(input(...)) raises ValueError if the user enters non-numeric text. Validate conversion before applying numeric conditions:

try:
    age = int(input("Enter your age: "))
except ValueError:
    print("Please enter a whole number")
else:
    if 21 <= age <= 100:
        print("Accepted")
    else:
        print("Outside the range")

Membership eligibility example

Several requirements can be combined in one condition. This example requires a person to be old enough and not have a suspended account:

age = 25
account_suspended = False

if age >= 21 and not account_suspended:
    print("Membership access allowed")
else:
    print("Membership access denied")

The and operator requires both requirements. The not operator turns account_suspended = False into a true access requirement.

Quick reference

  • Use and for requirements that must all be true.
  • Use or for alternatives where any true condition is enough.
  • Use not to reverse a Boolean condition.
  • Use <= and >= when a range includes its endpoints.
  • Use chained comparisons such as 21 <= age <= 100 for readable ranges.
  • Add parentheses to make mixed and/or grouping explicit.
  • Place safe guard conditions first when relying on short-circuit evaluation.
  • Check every boundary and ensure adjacent elif ranges have no gaps or overlaps.

For related lessons, review Python comparison operators, if, elif, and else statements, and catching specific exceptions.