Teaching a Program to Choose
A program that always does the same thing is not a program, it is a constant. Feed one input through a chain of conditions and watch exactly one branch of it ever run.
A program that always does the same thing is not a program, it is a constant. Feed one input through a chain of conditions and watch exactly one branch of it ever run.
A program that chooses
if age >= 18: print("adult")else: print("not an adult")if tests a condition. If it is true, the indented block underneath runs and Python skips the else entirely. If it is false, the if block is skipped and the else runs instead. Never both.
The indentation is not decoration. It is what tells Python which lines belong to the branch — four spaces in, consistently, or the interpreter cannot tell where the block ends. Mix tabs and spaces, or dedent one line by accident, and you get an IndentationError before the program runs at all.
Comparisons can be chained
Checking that a number sits between two bounds usually means writing the same variable twice, joined with and: age >= 13 and age < 20. Python lets you write the comparison the way you would say it out loud instead.
$ >>> age = 16$ >>> 13 <= age < 20$ True13 <= age < 20 checks both comparisons and combines them with an implicit and — age is evaluated once, not twice, and reads left to right exactly like the number line it describes. This is not a special case bolted onto if; it works anywhere a boolean expression is allowed.
elif is not a second if
Stack two separate if statements and Python checks both of them, every time, even after the first one already matched. elif checks only if everything above it was false — and the moment one branch matches, every branch after it is skipped without being evaluated at all.
if score >= 90: grade = "A"elif score >= 80: grade = "B"elif score >= 70: grade = "C"else: grade = "F"A score of 95 matches the first condition and stops there — the score >= 80 check never runs, because it does not need to. Write this as four separate if statements instead and a score of 95 would still pass the second and third tests too, which does no harm here only because each branch happens to overwrite grade rather than act on it.
if age >= 18:
print("adult")elif age >= 13:
print("teenager")else:
print("child")age >= 18 is false, so Python checks the elif. age >= 13 is true, so this branch runs and the else is skipped.
Python has no switch statement, on purpose
Plenty of languages let you match one value against a list of cases with a switch keyword. Python never had one — a chain of elif does the same job, and for most of the language's life that was considered enough.
$ >>> command = "start"$ >>> match command:$ ... case "start":$ ... print("starting")$ ... case "stop":$ ... print("stopping")$ ... case _:$ ... print("unknown command")$ ...$ startingPython 3.10 added match, which reads closer to a switch but does more — it can pull a sequence or a dictionary apart while it matches, not just compare a single value. case _: is the catch-all, matching anything nothing above it caught, the same role else plays at the end of an elif chain.
elif chain
Reads clearly for a plain sequence of comparisons. Works on every Python version. The default choice.
match statement
Use it when you are pulling a value apart by its shape — a tuple, a dictionary, a class — not just comparing it. Python 3.10 and newer only.
Guard clauses flatten the nesting
A function that checks three things before doing its real work is tempting to write as three nested if statements, one indent deeper than the last. Read it back a week later and the actual logic is buried at the bottom of a staircase.
$ def process(order): if order is not None: if order.items: if order.paid: ship(order) else: print("not paid") else: print("empty order") else: print("no order")
Rewritten as guard clauses, each check exits early and the real work sits at the top level, not nested four deep:
$ def process(order): if order is None: print("no order") return if not order.items: print("empty order") return if not order.paid: print("not paid") return ship(order)Each guard states one failure and returns immediately, so by the time you reach the bottom of the function, every condition that could have gone wrong already has not. The reader never has to hold three levels of "what if this branch is also true" in their head at once.
What Python accepts in place of true or false
A condition does not have to be written as a comparison. Any value can sit after if, and Python converts it to True or False the same way bool() would.
$ >>> name = ""$ >>> if name:$ ... print("has a name")$ ... else:$ ... print("empty")$ emptyAnother piece of syntax is the walrus operator := lets you assign a value and test it in the same expression, instead of on the line before.
$ >>> data = [1, 2, 3, 4, 5]$ >>> if (n := len(data)) > 3:$ ... print(f"{n} items, that's plenty")$ 5 items, that's plentyWithout it you would compute len(data), store it in n on its own line, then test n — three steps for one idea. It is a small convenience, reached for occasionally rather than by default.
Key takeaways
- Exactly one branch of an if/elif/else chain runs. Once one matches, everything after it is skipped.
- elif only gets checked if every condition above it was false — unlike a stack of separate if statements.
- Chained comparisons like 13 <= age < 20 evaluate the middle value once and read left to right.
- Python has no switch statement; match, from 3.10 onward, does more than a switch but is worth it only when you are pulling a value apart by shape.
- Guard clauses that return early replace a staircase of nested ifs with a flat list of failure checks, leaving the real work unindented.
Quick check
Answer these to unlock the next chapter — 3 of 4 to pass. You can retake it anytime.
Answer every question to check.
Make a free account to read on
Every chapter is free — an account is how your progress, XP, and streak follow you from your laptop to your phone, and how you show up on the leaderboard. No payment, no trial.