How does Python decide which branch of an if/elif/else chain executes?
answer
- Order is not cosmetic
- Think top to bottom
- How many blocks can run?
- Later conditions may never be evaluated
- else is the catch-all
basics
~10 sConditions are tested top to bottom and the first truthy one wins: its block runs and the whole rest of the chain is skipped. If none is true, the optional else block runs.
solid answer
~50 sAn `if`/`elif`/`else` chain is a single statement with one entry point. Python evaluates the `if` condition, then each `elif` condition in written order, and stops at the first one that is truthy; that block runs and every remaining condition is left **unevaluated**. At most one block ever executes, so the chain is a choice, not a filter. If nothing matches, the `else` block runs, and if there is no `else` the statement simply does nothing. Two consequences matter in review: **order encodes precedence**, so moving an `elif` up or down can change behaviour whenever two conditions can both be true; and a later condition with a side effect or a cost (a lookup, a regex, a network read) may never happen at all. A run of separate `if` statements is a different thing entirely — each is tested independently, and several of them can fire.
code
python · 14 linesdef positive(n):
print("evaluated positive()")
return n > 0
x = 5
if x > 1:
result = "gt1"
elif positive(x):
result = "positive"
else:
result = "other"
print(result) # gt1, and positive() never rango deeper
Be ready to state the rule cleanly: conditions run top to bottom, the first truthy one wins, at most one block executes, and else catches everything left. Have a two-line example ready.
Explain the mechanics: evaluation is lazy so later conditions may never run, order encodes precedence whenever conditions overlap, and an elif chain differs from separate if statements because only one block can fire.
Show the review instinct. Point out that reordering a branch is a semantic change, that a chain used to accumulate labels should have been separate ifs, and that expensive or side-effecting conditions belong late, not early.
Own the convention. Decide when a decision belongs in a flat chain that a reviewer can read at a glance versus a structure the type system or tests can prove total, and make branch ordering a documented rule rather than folklore.
### The rule in one line An `if` / `elif` / `else` chain is **one compound statement**, and Python runs **at most one** of its blocks: it evaluates the conditions in the order they are written and jumps into the first block whose condition is truthy, skipping everything else. ```python if a: ... # runs only if a is truthy elif b: ... # runs only if a is falsy AND b is truthy elif c: ... # runs only if a and b are falsy AND c is truthy else: ... # runs only if a, b and c are all falsy ``` There is no scoring, no best-match, no fall-through into the next block the way a C `switch` falls through without `break`. First match wins, then the statement is finished. ### Evaluation is lazy, and that is observable The conditions are not all computed up front. Python evaluates one, decides, and only evaluates the next if the current one was falsy. So a condition further down the chain can be an expression that is expensive, that has a side effect, or that would raise — and none of that happens once an earlier branch has matched. ```python def positive(n): print("evaluated positive()") return n > 0 x = 5 if x > 1: result = "gt1" elif positive(x): # never called: the first condition already won result = "positive" ``` This is the same short-circuit discipline you get from `and` and `or`, applied at statement level. It is a feature: you can safely write `if obj is None: ... elif obj.ready(): ...` because the attribute access is only reached when `obj` is not `None`. ### Order is precedence Because the first truthy condition wins, **the order of the branches is part of the program's meaning** whenever two conditions can both be true for the same input. A chain of numeric thresholds is the classic case: `score >= 90` must be tested before `score >= 60`, because a score of 95 satisfies both and only the first one reached will run. Reordering an `elif` is therefore a semantic edit, never a cosmetic one — treat it in review the way you would treat changing an operator. When the conditions are genuinely mutually exclusive (`status == "new"`, `status == "paid"`, `status == "void"`), order does not affect correctness, only readability and, marginally, how many comparisons run for the common case. ### `elif` versus separate `if` statements This is the distinction interviewers actually probe. A chain expresses *choose one*; a sequence of independent `if` statements expresses *apply each that fits*. ```python n = 12 tags = [] if n % 2 == 0: tags.append("even") if n % 3 == 0: tags.append("multiple of 3") # tags == ['even', 'multiple of 3'] -- both ran ``` Swap the second `if` for an `elif` and you get `['even']` only. Bugs in both directions are common: an accumulation loop written with `elif` silently drops labels, and a decision written with separate `if`s lets a later branch overwrite an earlier one's result. `elif` is also not merely cosmetic sugar for a nested `else: if ...`. It is semantically identical, but it keeps the whole chain at one indentation level, which is exactly what stops a five-way decision from becoming a five-deep staircase. ### Conditions are truthiness tests, not boolean tests The condition may be any expression. Python asks the object whether it is truthy, so `if items:` matches a non-empty list and `elif items is None:` after it would be dead code for the empty-list case. You do not need `== True`, and writing it narrows the test in ways that surprise people. ### No `else` is legal The `else` clause is optional. Without it, an input that matches nothing simply falls out of the statement and execution continues on the next line — no error, no diagnostic. In a function whose branches each `return`, that fall-through means the function returns `None` implicitly, which is a common source of a failure that surfaces far from the chain that caused it. ### What the interviewer is listening for At junior level: top to bottom, first match, at most one block, `else` is the catch-all. One layer down: laziness (later conditions may never be evaluated), order as precedence, and the `elif`-versus-separate-`if` distinction stated crisply with an example. Those three points are the whole answer.
- If two branches of an if/elif chain would both be true, which one runs?The one written first. Python stops at the first truthy condition, so the earlier branch shadows the later one for every input both accept. That is why threshold chains must be ordered narrowest-first, and why moving an `elif` is a behaviour change rather than a formatting change.
- Are all the conditions in an elif chain evaluated before Python picks a branch?No. Evaluation is lazy and stops at the first truthy condition, so later conditions may never run at all. Anything a later condition would have done -- a lookup, a mutation, a log line, an exception -- simply does not happen. It is the same short-circuit behaviour `and` and `or` give you, applied at statement level.
- Is `elif` different from writing `else:` followed by a nested `if`?Not semantically -- `elif` is exactly that, spelled without the extra indentation level. The difference is structural: `elif` keeps every alternative at the same indentation, so a six-way decision reads as a flat list instead of a six-deep staircase. That is the whole reason the keyword exists.
It is a queue at a single door, not a set of parallel gates: the first person whose ticket is valid goes through and the door closes behind them.
saying these in an interview costs you the question
- Says Python evaluates every condition and picks the best match
- Thinks two elif blocks can both run when both conditions are true
- Believes reordering elif branches is always safe
- Confuses an elif chain with a run of separate if statements
- Assumes a chain without else guarantees some block runs