Programming foundations · Control flow
Conditionals & decision logic
One value walks down an else-if ladder and exactly one branch runs. This page traces marks = 72 rung by rung, then writes the same four conditions in the wrong order and watches the same student get a different grade.
Walk 72 down both ladders →01 The idea
Ask a question, and only ask the next one if the answer was no
Code that runs straight down the page can do exactly one thing. Real programs have to choose: pass or fail, admin or student, cash or card. A conditional is how you write that choice — a question that is either true or false, and a block of code that runs only when it is true.
Once there is more than one outcome you stop writing separate questions and start writing a ladder. Ask the first question. Only if the answer is no, ask the second. That "only if" is the part that catches people out, because a rung the value never reaches cannot be right or wrong. It is simply dead code that looks alive.
02 Hand trace
marks = 72, one rung at a time
Five grade bands: 90 and above is an A, 75 and above a B, 60 and above a C, 40 and above a D, and anything below 40 is an F. Written as a ladder with the highest band first, that is four conditions and one else. Push marks = 72 into it and follow 72 down the rungs. A rose box is a condition that was tested and came back false. A green box is the one that came back true. A plain box was never touched.
Two numbers matter more than the answer. The first is three: only three of the four conditions were evaluated, and the else is never evaluated at all — it is simply what is left. The second is one: exactly one branch ran. The ≥40 rung is also true for 72 — the machine simply never asked it, because the chain had already exited. That is the whole mechanism, and it is why the next section can break this ladder without changing a single condition.
03 Code
Same four conditions, two orders, two grades
The trace worked because the rungs were in descending order. Put the same conditions in ascending order and every line is still legal. The program compiles, nothing crashes, no warning appears — and the answer is wrong. This is the failure mode you need to recognise on sight.
Wrong order · lowest band first
if marks >= 40: grade = "D" # loosest test firstelif marks >= 60: grade = "C" # unreachableelif marks >= 75: grade = "B" # unreachableelif marks >= 90: grade = "A" # unreachableelse: grade = "F"# marks = 72 -> "D" after 1 test
Right order · highest band first
if marks >= 90: grade = "A" # tightest test firstelif marks >= 75: grade = "B"elif marks >= 60: grade = "C" # 72 stops hereelif marks >= 40: grade = "D"else: grade = "F"# marks = 72 -> "C" after 3 tests
Order is the logic, not a style choice. Both blocks hold the same four conditions, the same else and the same five grades. Only the sequence differs. On marks = 72 the left block stops at rung 1 and answers D; the right block walks to rung 3 and answers C. Nothing else was edited.
The lower rungs are not wrong, they are unreachable. Any mark that reaches elif marks >= 60 in the left block has already failed marks >= 40, so it is under 40 and cannot possibly be 60 or more. The same argument kills rungs 3 and 4. That five-rung ladder has exactly two branches that can ever run: the first one and the else. Every passing student gets a D.
Nesting says the same thing with more room to get it wrong. You could write this as if marks >= 40: with another if marks >= 60: inside it. Nesting is the right tool when the inner question only makes sense once the outer one passed — check the file exists, then read it. When both tests sit on the same axis, keep the ladder flat: you can read the thresholds straight down the page and see at a glance whether they descend.
The other way to write a choice: switch
A switch compares one value against constant labels and jumps to the match. It cannot express a range, so it can never replace the ladder above — but it is the usual shape once you already have the grade letter. It also carries the single most famous bug in this module.
switch (grade) { // grade = 'C', from marks = 72 case 'A': msg = "Distinction"; break; case 'B': msg = "First class"; break; case 'C': msg = "Second class"; // break forgotten default: msg = "Needs work"; // runs as well} // msg ends up "Needs work"
A case runs on until it hits a break. switch jumps to the matching label and then keeps executing forward, ignoring every label it passes. Our C student matches case 'C', sets "Second class", finds no break, and falls straight into default. Fall-through is deliberate only when you stack labels with no code between them — case 'A': case 'B': to give two grades one shared block. Python has no such thing; its match never falls through.
05 Cheat sheet
What gets asked about conditionals
| Construct | Written as | What catches people |
|---|---|---|
| Two separate ifs | if a: … if b: … | Both blocks can run. As grade bands, marks = 72 sets C and then D, and the last assignment wins. |
| if / else | if a: … else: … | Exactly one of the two runs. The else binds to the nearest unmatched if, which is why braces matter in C and Java. |
| else-if ladder | if / elif / else | Top to bottom, first true wins, the rest are never evaluated. Order is the logic. |
| Nested if | if a: if b: … | The inner test runs only when the outer passed. Two independent tests belong in a and b, not in two levels. |
| switch on one value | case v: … break; | Equality against constants only — no ranges. A missing break falls through into the next case. |
| Ladder with no else | if / elif | Zero branches can run. Whatever the branches were meant to set silently keeps its old value. |
06 Where & why
Ladder, switch, or a table of data
A ladder is the most general of the three and the hardest to read once it passes about five rungs. What you buy is that any expression at all can go in a rung — ranges, two different variables, a function call. A switch cannot do that, and a lookup table cannot either.
Reach for a ladder when…
Use something else when…
| Situation | Better choice | Why |
|---|---|---|
| Every rung compares the same variable to a constant — a menu choice, a status code, a day name | switch / match | One value against many labels reads better, and a compiler can often jump straight to the case instead of testing rungs one by one. |
| Each rung only maps a key to a value — grade to message, code to label | A dictionary or lookup table | msg[grade] is one line, and adding a band means adding a row of data rather than another branch to order correctly. |
| The band boundaries are data an admin can change | A sorted array of (threshold, grade) pairs | The ordering is enforced by sorting the array instead of by whoever typed the rungs, and a new band needs no code change. |
| You are choosing between exactly two values | A conditional expression | "pass" if marks >= 40 else "fail" is one expression with no rungs to put in the wrong order. |
07 Interview questions
Say these out loud
The ladder-order question and the missing-break question are the two that actually come up. Both are read-this-code questions, not define-this-term questions.
What is the difference between an if / else-if chain and a series of separate if statements?
Does the order of conditions in an else-if ladder matter?
Walk me through what happens to marks = 72 in the grade ladder.
How many conditions are evaluated in the best and worst case?
What is short-circuit evaluation and why does it matter inside a condition?
What happens if you write = instead of == inside an if?
Why should you never compare two floating-point numbers with ==?
What is fall-through in a switch, and when is it useful?
if-else ladder or switch — which do you pick and why?
When is nesting better than a flat ladder, and when is it worse?
Can an else-if ladder run zero branches?
When would you actually use this?
08 Practice problems
Read the ladder before you write one
For each one, pick a single value and walk it down the rungs in written order. If you cannot say which rung it stops at, the ladder is not finished yet.