Logical Operators and Boolean Expressions
Short-circuit evaluation stops evaluating a logical expression once the result is already determined.
Why Evaluation Order Matters
A logical expression can contain more than one condition. Python evaluates those parts from left to right, but it does not always evaluate every part. When the result is already determined, Python stops. This behavior is called short-circuit evaluation.
The central rule is simple: and stops when the first part is False, while or stops when the first part is True.
Tracing a Logical Expression
Following an and expression
Trace the expression x >= 2 and (x/y) > 2 when x is less than 2.
- 1Check the first part
Because x is less than 2, x >= 2 evaluates to False.
- 2Apply the and rule
In an and expression, a False first part makes the entire expression False. Python therefore does not evaluate (x/y) > 2.
- 3Check the consequence
Since the division is not attempted, a zero value for y does not cause a
ZeroDivisionErrorin this case.
The expression is False, and the second part is skipped.
What do you think happens?
What happens when x is less than 2 and y is zero in x >= 2 and (x/y) > 2?
Reveal answer
Python stops after the first part and the expression is False.
The first part is False. That already determines the result of an and expression, so Python never evaluates the division.
The Two Short-Circuit Rules
| Operator | First part | What Python does | Reason |
|---|---|---|---|
| and | False | Stops and does not evaluate the later part | The entire and expression must be False |
| and | True | Evaluates the later part | The later part is needed to determine the result |
| or | True | Stops and does not evaluate the later part | The entire or expression must be True |
| or | False | Evaluates the later part | The later part is needed to determine the result |
The first operand determines whether Python can stop evaluating.
The two operators use opposite stopping conditions. With and, the first part must be False to prevent the later part from running. With or, the first part must be True to prevent the later part from running. The operator and the guard condition must therefore be chosen together.
Using the Guardian Pattern
The guardian pattern places a safe guard condition before a risky operation in a logical expression. If the guard makes the first part False in an and expression, Python stops before evaluating the risky operation.
In x >= 2 and (x/y) > 2, x >= 2 is the guard and (x/y) > 2 is the risky operation. When x is less than 2, the guard is False. The and expression is then already False, so Python never attempts the division. If the guard is True, Python continues and evaluates the second part.
The same pattern can protect a list access. The guard len(my_list) > 0 ensures that my_list[0] is accessed only when the list is not empty. When the list is empty, the guard is False and the list access is skipped, preventing an IndexError.
Mistakes Beginners Make
Common mistake Assuming Python always evaluates both parts of a logical expression
What it looks likeTreating x >= 2 and (x/y) > 2 as if the division always occurs
Why it failsWhen x >= 2 is False, the and result is already determined, so Python skips the division.
Do this insteadTrace the first part first and ask whether it already determines the result.
Common mistake Reversing the short-circuit rules
What it looks likeExpecting and to stop on True or or to stop on False
Why it failsThe stopping conditions are opposite: and stops on False, while or stops on True.
Do this insteadRemember that a False first part settles and, and a True first part settles or.
Common mistake Putting the risky operation before the guard
What it looks likeEvaluating a division before checking the condition intended to protect it
Why it failsPython evaluates from left to right, so a later guard cannot prevent an earlier operation from running.
Do this insteadPlace the safe guard first.
Common mistake Choosing an operator without considering the guard's required result
What it looks likeUsing an operator whose short-circuit condition does not match the guard
Why it failsAn and expression needs a False first part to skip its second part, while an or expression needs a True first part.
Do this insteadChoose the operator and guard condition together.
Practice the Trace
For each situation, identify whether Python evaluates the later part of the expression. Explain your answer using the words guard, short-circuit, and result already determined.
Hints
- For and, ask whether the first part is False.
- For or, ask whether the first part is True.
- Check the expression from left to right.
Practice answer
Analyze x >= 2 and (x/y) > 2 when x is less than 2 and y is zero.
- 1Identify the guard
The first part, x >= 2, is the guard.
- 2Evaluate the guard
Because x is less than 2, the guard is False.
- 3Apply short-circuit evaluation
The and expression is already False, so Python skips the later division.
No division is attempted, so this expression does not raise ZeroDivisionError in this situation.
Key Takeaways
- 1Python evaluates logical expressions from left to right and stops when the result is already determined.
- 2An and expression short-circuits when its first part is False.
- 3An or expression short-circuits when its first part is True.
- 4The guardian pattern places a safe condition before a risky operation.
- 5Correct guard order can prevent runtime errors such as
ZeroDivisionErrorandIndexError.
At a glance
- Short-circuit evaluation means Python may skip later parts of a logical expression.
- The and operator stops on a False first part; the or operator stops on a True first part.
- A guardian condition must appear before the operation it protects.
- The guardian pattern can prevent errors by ensuring that a risky expression is evaluated only when its required condition is met.