Python if, elif and else
Objective 2.1 is one line of blueprint - make decisions and branch the flow with the if instruction - and part of the densest 29% in PCEP. The syntax is small: `if`, `if`/`else`, `if`/`elif`/`else`, nesting, and the conditional expression. What gets asked is subtler: which branch runs when two conditions are both true, what counts as a true condition, and what an `if` with nothing in its body does.
Control Flow Guide 10 of 26 Beginner
- Python3.14.4
- OSUbuntu 26.04 LTS
- pip25.1.1
- TimeAbout 15 min
- Reviewed23 August 2026
Written against the versions above. Unchanged since Python 3.0. Python 3.10 added a `match` statement, which is a structural pattern matcher rather than a switch and is **not** on either syllabus - if a question offers `switch` or `case` as Python keywords, neither is one. See {{guide:keywords-indentation-and-comments}} on soft keywords.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| RUNNER01 | 192.168.0.27 | Ubuntu 26.04 LTS | Python 3.14.4 - the only machine this path needs | 2 Core | 4 GB | 50 GB |
Before you start
-
The three forms
There are exactly three, and the third is the second with extra branches in the middle.
ifalone runs its block or does not.if/elsechooses one of two.if/elif/elsechooses one of many, and the finalelseis optional even here.Every branch header ends in a colon and owns an indented block.
bash Example session cat > ~/py/ifforms.py <<'PY'n = 7 if n > 5: print("just if") if n > 100: print("not this")else: print("if-else took the else") if n < 0: print("negative")elif n == 0: print("zero")elif n < 10: print("single digit")else: print("ten or more")PYpython3 ~/py/ifforms.pyjust ifif-else took the elsesingle digitExpected result
just if,if-else took the else,single digit.Success conditionYou can write all three forms and trace which block runs.
-
elif order decides the answer
This is the trap in objective 2.1, and it is asked far more often than the syntax. Look at
classifybelow and work out whatclassify(500)returns.500 is greater than 100. It is also greater than 0.
bash Example session cat > ~/py/elifordering.py <<'PY'def classify(n): if n > 0: return "positive" elif n > 100: return "over a hundred" else: return "zero or negative" print(classify(500))print(classify(5))print(classify(-5))PYpython3 ~/py/elifordering.pypositivepositivezero or negativeExpected result
positive- notover a hundred.Success conditionYou can spot an unreachable
elifbranch by reading the order. -
A condition does not have to be a comparison
ifevaluates whatever you give it for truthiness - the same rule asbool()from guide 8. There is no requirement that it be a comparison, and no requirement that it be a boolean at all.Seven values, each used directly as a condition.
bash Example session cat > ~/py/iftruthy.py <<'PY'for value in (0, 1, "", "0", [], [0], None): if value: print(repr(value), "-> took the if") else: print(repr(value), "-> took the else")PYpython3 ~/py/iftruthy.py0 -> took the else1 -> took the if'' -> took the else'0' -> took the if[] -> took the else[0] -> took the ifNone -> took the elseExpected result
0,'',[]andNonetake the else;1,'0'and[0]take the if.Success conditionYou can use any value as a condition and predict the branch.
-
Nesting, and what determines it
An
ifcan contain anotherif. Nothing marks the nesting except indentation - there is noendand no closing brace - so whichelsebelongs to whichifis decided entirely by how far the line is indented.bash Example session cat > ~/py/nested.py <<'PY'n = 7 if n > 5: if n > 10: print("over ten") else: print("between six and ten")else: print("five or less")PYpython3 ~/py/nested.pybetween six and tenExpected result
between six and ten.Success conditionYou can read a nested branch and match each
elseto itsif. -
The conditional expression
Python's one-line branch is
A if condition else B. It is an expression - it produces a value - which is why it can sit on the right of an assignment where a statement cannot.Note the order: the *result* comes first, then the condition. Most languages put the condition first.
bash Example session cat > ~/py/ternary.py <<'PY'x = 5label = "big" if x > 3 else "small"print(label)print("even" if x % 2 == 0 else "odd")print(("small", "big")[x > 3])PYpython3 ~/py/ternary.pybigoddbigExpected result
big,odd,big.Success conditionYou can read and write a conditional expression.
-
An if body cannot be empty
A colon promises an indented block, and a comment is not a statement - the lexer removes comments before the parser sees them, so a block containing only a comment is an empty block.
The fix is
pass.bash Example session printf 'if True:\n# nothing here\nprint("after")\n' > ~/py/emptyif.py && python3 ~/py/emptyif.py File "/home/sysadmin/py/emptyif.py", line 3 print("after") ^^^^^IndentationError: expected an indented block after 'if' statement on line 1[exit 1]cat > ~/py/passif.py <<'PY'if True: passprint("pass filled the block")PYpython3 ~/py/passif.pypass filled the blockExpected result
IndentationError: expected an indented block after 'if' statement on line 1, then thepassversion running cleanly.Success conditionYou can satisfy an
ifthat has nothing to do yet. -
What the exam does with this objective
Objective 2.1 is roughly half of block 2's 29%, so around four or five questions. The shapes:
"Which branch runs?" - given a chain where the value matches two conditions. Top to bottom; the first true one.
"What is wrong with this code?" -
else ifinstead ofelif, a missing colon, or an empty block."Which
elsebelongs to whichif?" - read the indentation columns."Is this condition true?" - a bare value rather than a comparison; apply the truthiness rule.
"Rewrite this as one line." - the conditional expression, with the result before the condition.
The single most valuable habit is to read the order of an
elifchain before reading its logic, because an unreachable branch is invisible if you read the conditions individually.guide 11 is next, for the other half of block 2.
bash rm -f ~/py/ifforms.py ~/py/elifordering.py ~/py/iftruthy.py ~/py/nested.py ~/py/ternary.py ~/py/emptyif.py ~/py/passif.py && ls -A ~/pyExpected resultAn empty scratch directory.
Success conditionYou can answer every branching question shape this objective produces.
Troubleshooting
SyntaxError: invalid syntaxon a line readingelse if x > 5:.Why: Python spells it
elif. There is noelse if.Fix:Use
elif. A nestedifinside anelseblock is the other valid spelling, and it means the same thing with more indentation.An
elifbranch never runs, and no error is reported.Why: An earlier condition in the chain also matches. The first true condition wins and the rest are never tested.
Fix:Order conditions most-specific first:
n > 100beforen > 0. Python does not warn about unreachable branches.IndentationError: expected an indented blockon anifthat has a comment under it.Why: Comments are removed before parsing, so the block is empty.
Fix:Add
pass. Keep the comment if you like - it just cannot be the only thing there.if x == True:behaves differently fromif x:.Why: They are different tests. The first compares for equality with
True; the second tests truthiness.Fix:Use
if x:.[0]is truthy but is not equal toTrue, and neither is2.SyntaxErroronx = "big" if n > 3.Why: A conditional expression must have an
else- it has to produce a value in every case.Fix:Add the
elsebranch, or use a normalifstatement if there genuinely is nothing to assign in the other case.