Teaching programs to make decisions — conditional execution, branching logic, nested decisions, and the discipline of tracing exactly which path a program takes
Chapter 5 gave you the tools to build conditions: Boolean values, comparison operators, logical operators, and compound expressions. You learned how Python evaluates whether something is True or False. Now you need to use those conditions to control what your program actually does.
This chapter teaches conditional execution — the ability to run different code depending on whether a condition is true or false. Every real program needs this ability. A password check needs it. A grade calculator needs it. A game menu needs it. An eligibility form needs it.
By the end of this chapter, you will be able to write if statements, else branches, and elif chains. You will trace which branch executes for a given input. You will recognize common mistakes in branching logic and you will design clear, correct conditional programs.
A vending machine dispenses an item only if you have inserted enough money. A library charges a late fee only if a book is overdue. A login screen shows an error only if the password is wrong. What do these situations have in common? Each one depends on a condition that determines which of two or more outcomes occurs. This chapter teaches you how to express exactly that kind of logic in Python — precisely, correctly, and in a way you can trace step by step.
By the end of this chapter, you should be able to:
if statement, including the condition, colon, and indented block.if/else statement and explain why exactly one branch always runs.elif chain to handle more than two mutually exclusive cases.elif chains and independent, separate if statements.if StatementThe keyword, the condition, the colon, the indented block; tracing a simple example with changing valueselse StatementsTwo-branch decisions; mutual exclusivity of if/else; password-check exampleelif for Multiple CasesHandling more than two cases; top-to-bottom evaluation; why condition order matters; chains with no elseMost of the programs you have written so far run every line, every time. Line 1 runs. Then line 2. Then line 3. The order is fixed, and every line executes.
Real programs do not work that way. A real program needs to ask: Is this condition true right now? And based on the answer, it takes one path or a different path. This is called conditional execution: some code runs only when a condition is satisfied.
You already see conditional logic everywhere in everyday life.
In every case, something happens under one condition and something else happens (or nothing happens) under a different condition. Python gives you a direct way to write this kind of logic. It is called an if statement.
Conditional execution is not just about if statements. It is a way of thinking about programs. Before you write a single line of code, ask: What decisions does this program make? What are the possible paths? What condition separates one path from another? What should happen in each case? Asking these questions before writing code is one of the habits that separates programmers who struggle from programmers who succeed.
if StatementThe simplest conditional in Python is an if statement with one branch.
Read that pattern carefully. There are four things to notice.
ifif as the start of a conditional statement. It must be lowercase. If and IF are not valid.True or False. Usually a comparison or logical expression, exactly like those you practiced in Chapter 5.: appears at the end of the if line. It is required. Forgetting it is one of the most common beginner errors.if line are indented. They run only when the condition is True. If the condition is False, they are skipped entirely.Here is a complete, concrete example:
When Python runs this program, it evaluates the condition temperature > 30. Since temperature is 35, the condition is True. Python runs the indented line and prints:
Now change the value:
Now the condition temperature > 30 evaluates to False. Python skips the indented line. The program runs and produces no output. That is conditional execution. The print() call only happens when the condition is satisfied.
The indented block can contain more than one line. Every indented line is part of the block.
All three print() calls are inside the block. All three run if the condition is True. All three are skipped if the condition is False.
Python uses indentation to define which lines belong to a block. This is not optional and it is not decorative. Indentation is part of Python's syntax.
In most programming languages, blocks are marked with braces {} or keywords like begin and end. Python instead uses indentation. The amount of indentation must be consistent within a block. The standard in Python is four spaces.
Trace this carefully. The first two print() calls are indented by four spaces. They belong to the if block and only run when score >= 60. The last print() call is not indented. It is back at the left margin, which means it is outside the if block. It runs regardless of the condition.
With score = 85, the output is:
If you change score to 45:
Only the unindented line runs. The block is skipped.
Mixing tabs and spaces. Python 3 does not allow mixing them. Use four spaces consistently; your editor should handle this automatically.
Inconsistent indentation within a block. If one line is indented four spaces and the next is indented five, Python raises an IndentationError.
Forgetting to indent at all. If the line after an if is not indented, Python raises an IndentationError.
Indenting when you should not. If you indent a line that should be outside the block, it will only run when the condition is true — which is probably not what you wanted.
Read your indentation carefully. Indentation errors are among the easiest mistakes to fix once you spot them, but they can be hard to see at first because you are reading meaning, not whitespace.
else StatementsAn if statement with no else creates a single optional branch. The block either runs or it does not, and in either case the program continues.
But many decisions have two sides. Either the condition is true and something happens, or the condition is false and something different happens. For this, Python provides the else clause.
The else keyword is followed by a colon and an indented block, exactly like if. The else block runs only when the if condition is False. Exactly one of the two blocks always runs. They are mutually exclusive.
With age = 16, the condition age >= 18 is False. The else block runs:
Change age to 20:
The if block runs, and the else block is skipped. Notice that the program always produces output. Whether the condition is true or false, one of the branches runs. That is the point of else: it ensures that something happens in every case.
entered_password == correct_password compares the two strings, which are not equal, so the condition is False.else branch runs, printing "Incorrect password. Please try again."elif for Multiple Casesif and else handle two cases: the condition is true, or the condition is false. But many real decisions involve more than two cases. Consider assigning a letter grade:
| Score Range | Letter Grade |
|---|---|
| 90 or above | A |
| 80 to 89 | B |
| 70 to 79 | C |
| 60 to 69 | D |
| Below 60 | F |
That is five distinct cases. You cannot handle five cases with just if and else. You need a way to check a series of conditions in order. Python provides elif, which stands for else if. An elif clause adds another condition to test if the previous conditions were all false.
Python evaluates the conditions from top to bottom. As soon as one condition is True, its block runs and the rest of the chain is skipped entirely. If no condition is true, the else block runs (if there is one). Here is the grade example:
With score = 83, Python evaluates the conditions in order: score >= 90 → 83 >= 90 → False, move on. score >= 80 → 83 >= 80 → True. Run this block and stop.
None of the remaining elif or else branches are evaluated. The chain stops as soon as one match is found.
Consider what happens if you reverse the order:
With score = 83, Python evaluates the first condition: 83 >= 60. That is True. So it prints Grade: D and stops. The student with an 83 is incorrectly assigned a D. This happens because elif chains stop at the first true condition. When the conditions overlap — as they do here — the order completely determines the result. Always arrange conditions from most specific (or highest threshold) to least specific, or think carefully about what each condition covers.
elseYou do not always need an else. If no condition is met and there is no else, nothing happens.
With temperature = 22, none of the conditions are true and there is no else. The program produces no output. This is sometimes what you want: only act if a notable condition occurs.
When you use if, elif, and else together, exactly one branch executes per run. The conditions are mutually exclusive within a chain: Python guarantees that once one branch runs, the rest are ignored. This is different from writing separate if statements.
Program A — elif chain | Program B — separate if statements |
|---|---|
| score = 95 if score >= 90: print("Excellent") elif score >= 80: print("Good") elif score >= 70: print("Satisfactory") | score = 95 if score >= 90: print("Excellent") if score >= 80: print("Good") if score >= 70: print("Satisfactory") |
With score = 95, Program A prints only Excellent because the chain stops after the first true condition. Program B prints all three, because each if is independent and Python evaluates all three conditions:
This is one of the most important structural decisions in conditional programming. Ask yourself: should exactly one thing happen, or can multiple things happen? Use elif chains for mutually exclusive cases. Use separate if statements when multiple conditions can independently apply.
if statements used correctlyAll three conditions can be independently true, so separate if statements are appropriate here.
Sometimes a decision depends on a previous decision. After Python takes one branch, you might need to make another choice inside that branch. This is called a nested decision: one if statement appears inside the block of another.
Trace this step by step. Python evaluates the outer condition: age >= 18. With age = 20, this is True. Python enters the outer block. Inside the outer block, Python evaluates the inner condition: has_ticket. Since has_ticket is True, Python runs the inner if block.
Now try age = 20 and has_ticket = False: the outer condition 20 >= 18 is True, so Python enters the outer block; the inner condition is False, so Python skips the inner if and runs the inner else.
Now try age = 15 and has_ticket = True: the outer condition 15 >= 18 is False, so Python runs the outer else.
Notice that the inner if block is never even reached when the outer condition is false. Python does not evaluate the inner condition because it is inside a block that did not run.
Each nested level adds four more spaces. Deep nesting — three or more levels — makes code hard to read. If you find yourself writing deeply nested conditionals, it is often a sign that the logic can be restructured.
Sometimes nesting can be replaced with a compound condition. Compare:
| Nested version | Compound condition version |
|---|---|
| if age >= 18: if has_ticket: print("Welcome.") | if age >= 18 and has_ticket: print("Welcome.") |
Both do the same thing. The compound version is shorter and often clearer when the logic is simple. Nesting is more appropriate when the two decisions have different consequences — when you need separate else branches for each level.
Writing a conditional statement that technically works is not enough. The goal is to write conditional logic that is correct, readable, and easy to verify. Here are the key questions to ask when designing branching logic.
elif. If they can overlap, use separate if statements.else to handle it? It acts as your safety net.elif chain, Python stops at the first true condition. Make sure the most important or most specific cases come first.elif chain is appropriate.With age = 14: 14 < 12 → False. 14 <= 17 → True. Set price = 9.00. Stop.
Notice that the conditions do not need to spell out the full range explicitly. Once age < 12 is false, you know age is at least 12. So age <= 17 catches ages 12 through 17 without needing to write 12 <= age <= 17. This relies on the order of evaluation — each elif implicitly knows that all previous conditions were false.
Trace with the given values: not fee_paid → not True → False. Move to elif. age < 18 and not parent_member → 15 < 18 and not True → True and False → False. Move to else. The else block runs.
This design checks the disqualifying conditions first (unpaid fee, missing parent membership) and only reaches "welcome" if everything passes. This pattern — check problems first, success last — is a useful habit for eligibility and validation logic.
Tracing is the process of following code exactly as Python executes it. Tracing conditional programs requires special attention because not all lines run every time. Which lines run depends entirely on the values of the variables and the conditions at each step.
1. Know the value of every relevant variable before each condition is evaluated.
2. Evaluate each condition to True or False.
3. Follow the correct branch.
4. Skip the branches that do not run.
5. Continue from the line after the full conditional structure.
x > 10 → 7 > 10 → False. Skip this block.x > 5 → 7 > 5 → True. Run this block.print("Medium") executes.else block.print("Done") executes.username == "admin" → True. Enter outer block.password == "secret" → "1234" == "secret" → False. Skip inner if.else block.a > b → 5 > 10 → False. Skip.a == b → 5 == 10 → False. Skip."B is larger". Sets a = b, so a = 10.10.Notice that the else block changes a. After the conditional structure, a has a new value. Conditional branches can modify variables, and those changes persist after the branch ends.
For complex programs, a tracing table helps you track variable values across steps. Here is a tracing table for the example above:
| Line | Action | a | b |
|---|---|---|---|
| Start | — | 5 | 10 |
if a > b | False, skip | 5 | 10 |
elif a == b | False, skip | 5 | 10 |
else: a = b | a gets value of b | 10 | 10 |
print(...) | Output: a = 10, b = 10 | 10 | 10 |
Tracing tables are especially useful when programs grow larger. You will practice them extensively in this chapter's exercises and in Chapter 10.
Conditional programs are prone to a specific set of mistakes. Knowing them in advance helps you spot them before they cause problems.
elif, using separate if statements insteadscore = 95, all three conditions are true. grade ends up as "C" because the last assignment wins. The student with a 95 is labeled C. The fix is to use elif so the chain stops at the first match.
==) is fragile for scores. What if the score is 74 or 76? Neither matches any condition, so the else runs and prints "Keep practicing" for a student with 74. More commonly you want ranges, not exact values.
score >= 50 is true for a score of 55, the chain stops immediately. The elif score >= 90 branch is dead code — it can never run for any score, because any score that is at least 90 is also at least 50, and the first condition will catch it first. Put more specific (or higher-threshold) conditions before more general ones.
= instead of equality == in a conditionSyntaxError here, which actually protects you. But the intent was x == 10. Remember: = is assignment, == is comparison.
SyntaxError. The colon is required at the end of every if, elif, and else line.
if block must be indented, or Python raises an IndentationError. All lines in the same block must also use the same indentation, or Python raises an IndentationError: unexpected indent.
score = 100.5? Or score = "eighty"? Conditionals only catch what you design them to catch. Think about your edge cases.
else when conditions do not cover all caseselse here correctly handles any color that is not red, yellow, or green. But if the else had been left out and the input was "purple", the program would silently do nothing. Always consider whether your chain needs a default case.
if statement has four parts: the keyword, the condition, the colon, and the indented block. The block runs only when the condition is True.else clause provides a second branch that runs only when the if condition is False. Exactly one of the two branches always executes.elif extends a chain to handle more than two cases. Python evaluates conditions top to bottom and stops at the first True condition, so order matters enormously when conditions overlap.Read each program carefully. Do not run it. Answer the questions below each program.
result equal after the conditional runs?result be if points = 50?result be if points = 49?greeting when hour = 14?greeting when hour = 9?greeting when hour = 23?greeting when hour = 17?print() calls execute?if statements used here instead of elif?y = 8?discount with membership = "gold" and years = 3?discount with membership = "gold" and years = 7?discount with membership = "silver" and years = 10?discount with membership = "bronze" and years = 2?For each program, trace the execution step by step and fill in the tracing table. Predict the output before checking.
| Step | Condition Evaluated | Result | Action |
|---|---|---|---|
| 1 | temperature >= 35 | ||
| 2 | temperature >= 28 | ||
| Output |
Complete the tracing table and write the full output.
| Line | Condition | Result | Output |
|---|---|---|---|
if n % 2 == 0 | |||
if n > 10 | |||
print("Finished") | — | — |
Trace this nested conditional with a = 3 and b = 7.
Write out:
print() runs.Study each program and predict the exact output. Write your answer before checking.
(Hint: recall from Chapter 5 that 0 is falsy in Python.)
Each program contains one or more errors. Identify each error, explain what is wrong, and write the corrected code.
What is wrong? Write the corrected code.
This program has a logic error for a student with a score of 85. What is wrong? Write the corrected code.
What is wrong? Write the corrected code.
What is wrong? Write the corrected code.
Identify the dead code in this program and explain why it can never run.
Write a program that asks the user for a number and prints whether it is positive, negative, or zero. Example output when input is -3:
Write a program that asks the user for their age and prints: "You may drive with a learner's permit." for ages 16 and 17; "You may drive with a full licence." for ages 18 and over; "You are not yet eligible to drive." for ages under 16.
A store offers these discounts on a purchase total:
| Purchase Total | Discount |
|---|---|
| Under $20 | No discount |
| $20 to $49.99 | 5% |
| $50 to $99.99 | 10% |
| $100 or more | 15% |
Write a program that reads a purchase total and prints the discount percentage and the final price after the discount.
Write a program that reads a month number (1 through 12) and prints the season: December, January, February → Winter; March, April, May → Spring; June, July, August → Summer; September, October, November → Autumn. Handle any month number outside 1–12 with an appropriate message.
Write a program that reads three side lengths and prints: "Equilateral" if all three sides are equal; "Isosceles" if exactly two sides are equal; "Scalene" if all three sides are different; "Invalid" if any side is zero or negative. Check for "Invalid" first, before the other cases.
Write a program that stores a correct username and password (as variables). Ask the user to enter a username and a password. Print "Access granted." if both match; "Wrong password." if the username matches but the password does not; "Unknown username." if the username does not match.
Design and write a program that takes a student's numeric score (0 to 100) and determines: their letter grade (A, B, C, D, or F) using standard thresholds; whether they qualify for an academic scholarship (score 90 or above); whether they are on academic probation (score below 60); and a short message appropriate to their result.
Before writing any code, write out in plain language: What are the valid and invalid inputs? What are the possible grade cases? What are the possible message cases? Are any decisions nested?
Add a second score (e.g., a midterm and a final). Compute the average and base the grade and messages on the average.
Write the Boolean value (True or False) that each expression produces:
10 > 5 and 3 < 210 > 5 or 3 < 2not (5 == 5)"hello" == "Hello"7 != 7A program stores x = 4. Write an if/else statement that prints "Even" if x is even and "Odd" if x is odd. Use the modulo operator %.
Explain in plain language what this program does. Then predict the output for n = 15.
A student writes this program to check whether a number is in a range:
Rewrite this using a single compound condition and a single if statement. What is the output for value = 50? For value = 150?
What is the difference between if/elif/else and a series of separate if statements? Describe a situation where you would use each.
Chapter 6 taught programs to make decisions. Now programs can take different paths. But programs also need to repeat work. Printing a hundred grades one by one is not practical. Counting votes manually is not practical. Processing thousands of entries one at a time in code would require thousands of lines. Repetition is one of the most powerful tools a program has. Chapter 7 introduces loops — the mechanism Python uses to repeat code. You will learn what a loop body is, how iteration works, how counters and accumulators keep track of repeated work, and the difference between repeating a fixed number of times versus repeating until a condition is met. Loops will also use conditions — the same Boolean logic and comparisons from Chapter 5. The skills from Chapters 5 and 6 feed directly into Chapter 7. Bring your understanding of True and False with you.