If, Elif, Else, and Decision Trees
Key Takeaways
- An if statement starts a decision tree; elif branches are tested in order only when all earlier conditions were false.
- Only the first true branch in an if/elif/else chain executes, even if later conditions would also be true.
- An else clause has no condition and runs only when no earlier branch in the same chain ran.
- Indentation alone decides branch membership, so visually similar snippets can behave very differently.
- PCEP branch questions are easiest when traced as condition-result-action rows rather than guessed from the printed output.
The shape of a decision tree
An if statement asks one question. If the condition is truthy, Python runs the indented block beneath it; if falsey, it skips that block and looks for an attached elif or else. Every header line ends with a colon, and the body is indented (PEP 8 recommends four spaces).
score = 82
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
elif score >= 70:
grade = 'C'
else:
grade = 'review'
print(grade) # B
This prints B. Note that score >= 70 is also true, but Python never reaches that branch because score >= 80 already succeeded. Within a single chain, exactly one branch can run: the first true branch, the else, or nothing if there is no else.
If versus elif: one chain or several decisions
Independent if statements are not the same as an if/elif/else chain. Each independent if is evaluated on its own.
x = 10
if x > 0:
print('positive')
if x > 5:
print('large')
else:
print('small')
This prints positive then large. The else belongs only to the second if. The classic trap is reading two independent decisions as one combined chain, or vice versa.
Indentation is structure
Python uses indentation, not braces, to decide block membership. A line at the same indentation as the if keyword is outside the branch.
ready = False
if ready:
print('start')
print('done')
Only done prints. Mixing tabs and spaces in the same block raises a TabError, and inconsistent indentation raises IndentationError.
Ordering range conditions
When branches test overlapping ranges, order is the answer. A broad test placed before a narrow test captures values the narrow test wanted.
points = 95
if points >= 60:
label = 'pass'
elif points >= 90:
label = 'honor'
label becomes 'pass', not 'honor', because points >= 60 is checked first. To get 'honor', the >= 90 test must come first. Order narrow-to-broad.
Nested decisions and the dangling else
A nested if puts a second decision inside a branch. Evaluate the outer condition first; only if that branch runs do you evaluate the inner one. Each else attaches to the nearest unmatched if at the same indentation level.
x = 5
if x > 0:
if x > 10:
print('big')
else:
print('small positive')
The inner else pairs with if x > 10, so this prints small positive.
Conditional (ternary) expressions
PCEP also tests the inline conditional expression value_if_true if condition else value_if_false:
n = -4
sign = 'neg' if n < 0 else 'nonneg' # 'neg'
This is one expression, not a statement block, and it always requires the else part.
Trace-table method
| Step | Condition | Result | Action |
|---|---|---|---|
| 1 | score >= 90 | False | skip A branch |
| 2 | score >= 80 | True | run B branch, stop chain |
| 3 | later elif | not checked | no action |
Exam traps: missing colons after if/elif/else; = instead of ==; writing else if instead of Python's elif; an else visually near one branch but indented under another; and forgetting that if name: runs when name is simply nonempty.
Multiple statements inside one branch
A branch can hold many statements; every line indented to the same level belongs to that branch. PCEP tests whether you stop at the right place.
x = 8
if x > 5:
x = x - 1
x = x * 2
print(x) # 14
Both assignments run because both are indented under the if. x becomes 7, then 14. If the second line were dedented, it would run unconditionally and the answer would change.
Conditions that are computed, not literal
The condition can be any expression with a truth value, including the result of a function or a membership test. PCEP commonly uses in, %, and length.
word = 'python'
if 'y' in word:
print('has y')
if len(word) % 2 == 0:
print('even length')
Both print, because 'y' is in 'python' and the length 6 is even. Membership (in) and remainder (%) checks appear constantly in branch questions, so practice reducing them to a boolean first.
Empty branches and pass
A branch must contain at least one statement. If you have nothing meaningful to do yet, Python requires a pass placeholder; an empty indented block is a SyntaxError.
if x > 0:
pass # legal placeholder
else:
print('non-positive')
Step-by-step evaluation discipline
For any branch question, follow this fixed routine:
- Identify whether the snippet is one chain or several independent ifs.
- Evaluate each condition top to bottom, stopping at the first true branch in a chain.
- Match every
elseto the nearest unmatchedif/elifat the same indentation. - Run only the indented body of the selected branch.
- Resume at the first line dedented back to the chain's level.
| Symptom in the code | Likely intended trap |
|---|---|
| Broad test before narrow test | Wrong branch wins on range overlap |
Two if headers, one else | The else pairs with only the second if |
| Statement dedented after a branch | It runs unconditionally, not as part of the branch |
elif written as else if | SyntaxError, not a valid branch |
Applying these five steps and scanning the trap table converts decision-tree questions from guesswork into a mechanical trace, which is exactly what the 40-minute time budget rewards.
What is printed by this code? x = 12 if x > 5: print('A') elif x > 10: print('B') else: print('C')
What is printed by this code? x = 3 if x > 0: print('P') if x > 5: print('L') else: print('S')
Which statement about an else clause is correct?
What does this conditional expression assign? n = 0 s = 'zero' if n == 0 else 'other'