This page is a drill . The parent topic note taught the rule ; here we hit every kind of case the rule can face, so you never meet a situation you haven't already seen solved.
Intuition How to read this page
For each example, first read the Forecast line and actually pause — say the answer out loud before scrolling. That gap between your guess and the truth is where the learning lives.
To talk about the rule compactly, we use a few plain-English abbreviations. You never type these in Python — they are just note-taking labels:
Definition The labels we use on this page
A condition is the true/false test after if or elif (e.g. temp < 10). We name them in order: the first is "test 1" , the second "test 2" , and so on.
A block is the indented group of lines under a header. We call them "block 1" (under if), "block 2" (under the first elif), etc., and "else-block" for the fallback.
"test N is False " just means that test evaluated to False.
That's the whole vocabulary. No mathematical symbols are needed to follow this page — every rule below is stated in these plain words.
Think of every if-decision as a machine that takes some input and must land in exactly one branch. What can that input be? Let's enumerate the "shapes" of situation:
Cell
Case class
What it stress-tests
A
First test True
Chain stops immediately, later tests never run
B
A middle elif True
Reaching block 2: test 1 False, test 2 True
C
All tests False → else
The fallback catches everything left over
D
Boundary / equality value
>= vs > at the exact edge (the "off-by-one" trap)
E
Zero / empty input (truthiness)
0, "", [] behave as False
F
No else present
Possibility that no branch runs
G
Nested block
A decision inside a decision, two indent levels
H
Separate ifs vs elif
Multiple branches running & overwriting
I₁
Compound condition with and
Both sides must be True
I₂
Compound condition with or (short-circuit)
Either side True is enough; stops early
J
Real-world word problem
Translating English into a chain
K
Exam twist
Order-of-tests bug you must spot
The 11 examples below cover every cell, one cell per example . The label after each title says which one.
Worked example 1 — First test wins (Cell A)
temp = 5
if temp < 10 :
print ( "cold" )
elif temp < 20 :
print ( "mild" )
else :
print ( "warm" )
Forecast: which single word prints?
Steps
Evaluate temp < 10 → 5 < 10 → True.
Why this step? Python checks conditions top to bottom and the first True ends the search.
Run that block → prints cold. Skip elif and else entirely — they are never even evaluated.
Why this step? The rule says the first True test wins; nothing after it matters once test 1 holds.
Verify: 5 < 10 is true and 5 < 20 is also true — but we never reached the second test, so there's no conflict. Output = cold. ✅
Worked example 2 — A middle branch fires (Cell B)
temp = 15
if temp < 10 :
print ( "cold" )
elif temp < 20 :
print ( "mild" )
else :
print ( "warm" )
Forecast: cold, mild, or warm?
Steps
temp < 10 → 15 < 10 → False. Skip block 1.
Why this step? Reaching the elif requires the if to have failed — test 1 being False is built in.
temp < 20 → 15 < 20 → True. Run block 2 → prints mild.
Why this step? Block 2 runs exactly when test 1 was False and test 2 is True — both hold here.
Verify: 15 is not below 10 but is below 20, so mild is exactly the "at least 10, under 20" band. Output = mild. ✅
Worked example 3 — Nothing matches,
else catches it (Cell C)
temp = 30
if temp < 10 :
print ( "cold" )
elif temp < 20 :
print ( "mild" )
else :
print ( "warm" )
Forecast: what prints when the value is high?
Steps
30 < 10 → False. Skip block 1.
Why this step? A False test means we move on to the next door.
30 < 20 → False. Skip block 2.
Why this step? Both tests false means we've walked past every door.
else runs unconditionally now → prints warm.
Why this step? The else-block runs exactly when every test above was False, and both were.
Verify: The three branches split all temperatures into "below 10", "10 up to under 20", and "20 and above". 30 lives in the last piece → warm. No gaps, no overlaps. ✅
Worked example 4 — The boundary value (Cell D)
marks = 40
if marks > 40 :
print ( "above pass" )
elif marks >= 40 :
print ( "exactly pass" )
else :
print ( "fail" )
Forecast: at exactly 40, do we print "above pass" or "exactly pass"?
Steps
marks > 40 → 40 > 40 → False. > is strictly greater ; equal is not greater.
Why this step? This is the classic off-by-one. > excludes the edge; >= includes it.
marks >= 40 → 40 >= 40 → True → prints exactly pass.
Why this step? >= means "greater or equal", so the boundary lands here.
Verify: Swap the value to 41: 41 > 40 is True, giving above pass. So the two branches split cleanly at the boundary. At 40 exactly → exactly pass. ✅
See Booleans and comparison operators for the full <, <=, ==, >=, > table.
Worked example 5 — Zero and empty values (Cell E, truthiness)
basket = []
if basket:
print ( "has items" )
else :
print ( "empty cart" )
Forecast: an empty list [] — is that "true" or "false" to Python?
Steps
Python asks: is basket truthy ? An empty list is treated as False.
Why this step? if doesn't need a real True/False; any value is coerced. See Truthiness in Python .
Condition is False → skip the if, run else → prints empty cart.
Why this step? Once the test counts as False, the fallback is the only branch left to run.
Verify: The falsy set is 0, 0.0, "", [], {}, (), None, False. If we set basket = [1] (one item), it becomes truthy → has items. Empty → empty cart. ✅
else: maybe nothing runs (Cell F)
n = 7
if n < 0 :
print ( "negative" )
print ( "done" )
Forecast: how many lines print?
Steps
n < 0 → 7 < 0 → False. Skip the indented block. negative does not print.
Why this step? With no else, a false if simply does nothing — there's no fallback.
print("done") is at the same indent as if , so it's outside the block and runs always.
Why this step? Indentation is the grammar: same level = "after the whole if". See Indentation and code blocks .
Verify: Only done prints (one line). With n = -7, both negative and done print (two lines). ✅
Worked example 7 — Nested decision (Cell G) — figure
age = 20
has_id = False
if age >= 18 :
if has_id:
print ( "entry granted" )
else :
print ( "bring ID" )
else :
print ( "too young" )
Forecast: an adult with no ID — which message?
The figure below is a flow map. What to see in it: a large black box (the outer if age >= 18 block) contains a smaller box (the inner if has_id block). Three outcome tags sit at the bottom: entry granted , bring ID , and too young . The red line traces the exact route our input takes — down through the outer test marked "True", then right out of the inner test marked "False" — and it ends at the red bring ID tag. The dashed black arrow shows the ignored "age False → too young" route; the thin black arrow shows the ignored "has_id True → entry granted" route.
Steps
Outer age >= 18 → 20 >= 18 → True. Enter the outer block (indent level 1).
Why this step? Only if the outer door opens do we even see the inner doors.
Inner has_id → False. So the inner if fails → its else runs → prints bring ID.
Why this step? The inner else (8 spaces) is matched to the inner if by its indentation, not the outer one.
Verify: Adult + no ID → bring ID. Adult + ID → entry granted. Under 18 → too young (never even checks has_id). All three leaf outcomes covered. ✅
Worked example 8 — Separate
ifs clobber each other (Cell H)
score = 85
grade = "?"
if score >= 80 :
grade = "B"
if score >= 70 :
grade = "C"
print (grade)
Forecast: you'd hope for B — what actually prints?
Steps
85 >= 80 → True → grade = "B".
Why this step? The first if passes, so its block sets the grade to "B" for now.
These are two independent ifs , not an elif chain — the second one is also evaluated.
Why this step? Separate ifs don't know about each other; there's no "stop at first True".
85 >= 70 → True → grade = "C", overwriting the "B".
Why this step? Because the second if also passes, its assignment replaces the earlier value.
Print → C.
Why this step? The variable now holds whatever the last matching block wrote.
Verify: The bug: the same 85 satisfies both tests, so the last assignment wins. Replacing the second if with elif would keep B. Output as written = C. ✅
Worked example 9 — Compound condition with
and (Cell I₁)
# A ride needs enough money AND a minimum height. You need BOTH.
height = 130 # cm
money = 50 # rupees
if height >= 120 and money >= 40 :
print ( "ride allowed" )
elif height < 120 :
print ( "too short" )
else :
print ( "not enough money" )
Forecast: tall enough and enough cash — which branch?
Steps
Evaluate the left side height >= 120 → 130 >= 120 → True.
Why this step? and looks at its left operand first, so we resolve it first.
Evaluate the right side money >= 40 → 50 >= 40 → True. Now True and True → True.
Why this step? and is True only when both sides are True. See Logical operators and, or, not .
Run block 1 → prints ride allowed; elif/else skipped.
Why this step? The combined test is True, so this is the first (and only) block that runs.
Verify: Test the other branches: height=100 → first test False (100>=120 is False), elif height<120 True → too short. And height=130, money=20 → first False (money), not short, so else → not enough money. All three reachable. Output for the given inputs = ride allowed. ✅
Worked example 10 — Compound condition with
or and short-circuit (Cell I₂)
# Free entry if you are a member OR it is a holiday. Either one is enough.
is_member = True
is_holiday = False
if is_member or is_holiday:
print ( "free entry" )
else :
print ( "pay entry" )
Forecast: a member on a normal day — free or pay? And does Python even look at is_holiday?
Steps
Evaluate the left side of or: is_member → True.
Why this step? or checks its left operand first.
Because the left side is already True, or short-circuits : it stops and returns True without ever reading is_holiday.
Why this step? or is True if either side is True, so once one True is found the answer can't change — Python saves work by not evaluating the rest. See Logical operators and, or, not .
Run the if block → prints free entry.
Why this step? The whole condition is True, so the first (only) block runs.
Verify: With is_member=False, is_holiday=False → False or False → False → else → pay entry. With is_member=False, is_holiday=True → the left is False so Python does read the right, finds True → free entry. Member on normal day → free entry. ✅
Worked example 11 — Word problem + exam twist: order-of-tests bug (Cells J and K)
# WORD PROBLEM: label a number as "big" (>100), "medium" (>10), else "small".
# But the author ordered the tests badly on purpose — spot the bug.
x = 500
if x > 10 :
label = "medium"
elif x > 100 :
label = "big"
else :
label = "small"
print (label)
Forecast: the author wanted big for 500. What actually prints — and why is the chain broken?
Steps
x > 10 → 500 > 10 → True → label = "medium", chain stops.
Why this step? The broadest test is checked first, so it swallows everything above 10; the first True wins and stops the chain.
The elif x > 100 is never reached, so 500 is mislabelled medium.
Why this step? Once test 1 is True Python skips all later elifs — a bigger threshold placed after a broader one can never fire.
Fix: order tests from most specific / largest threshold first down to the broadest.
Why this step? Putting x > 100 first means numbers over 100 match it before the x > 10 net can catch them.
if x > 100:
label = "big"
elif x > 10:
label = "medium"
else:
label = "small"
**Verify:** Buggy version on `500` → `medium`. Fixed version on `500` → `big`; on `50` → `medium`; on `3` → `small`. The fix restores all three bands. Buggy output as written = `medium`. ✅
Recall One-line summary of the whole matrix
Every input lands in exactly one branch: the first test that is True (truthiness included), or the else-block if none are — provided your tests are ordered specific-first and you use elif, not stacked ifs.
Cell A — if temp=5 in the cold/mild/warm chain, output? cold (first test True, rest never checked).
Cell D — if marks > 40 ... elif marks >= 40 with marks=40, output? exactly pass (> excludes the edge, >= includes it).
Cell E — is an empty list [] truthy or falsy? Falsy — it counts as False in a condition.
Cell H — two separate ifs both True, which assignment wins? The last one (later blocks overwrite earlier results).
Cell I₂ — in A or B with A True, does Python evaluate B? No — or short-circuits and returns True without reading B.
Cell K — why does if x>10 ... elif x>100 mislabel 500? The broad test x>10 fires first and stops the chain; put the larger threshold first.
1.2.15 if - elif - else — syntax, indentation rules (Hinglish) — the parent topic note
Booleans and comparison operators — <, <=, ==, >=, > produce the conditions
Logical operators and, or, not — building the compound tests in Examples 9 and 10
Truthiness in Python — why [], 0, "" act as False (Example 5)
Indentation and code blocks — how nesting in Example 7 is parsed
while and for loops — conditions reused to control repetition
match-case statement — a cleaner form when branching on one value's cases
Ternary conditional expression — the one-line a if cond else b shortcut