Programming in Python · Lesson 6

Decision Control Structures

If, if-else, nested-if, and elif structures, relational operators, Boolean expressions, fall through, and the logical operators and, or, and not.

  • decisions
  • if-statements
  • elif
  • relational-operators
  • boolean-logic
  • truth-tables

Lesson purpose

Until now, every program the class has written runs top to bottom, one statement after another. This lesson introduces decision control structures, which let a program choose which statements to run based on a condition. Students learn the four decision patterns (if-then, if-then-else, nested-if, and else-if), the relational operators used to build conditions, Boolean expressions and the Boolean data type, and the logical operators and, or, and not.

The logic will be familiar to students who know C# and JavaScript. Emphasize the Python-specific syntax: a colon ends every condition line, indentation (not braces) defines each block, the keyword is elif (not else if), the logical operators are the words and, or, and not (not &&, ||, !), and True and False are capitalized.

Learning objectives

By the end of the lesson, students should be able to:

  • Describe the purpose of control structures and identify algorithms that require decisions.
  • Illustrate if-then and if-then-else structures with flowcharts and pseudocode.
  • Identify the conditional statement in an if-then structure and code it in Python.
  • Differentiate between the = operator and the == operator.
  • List, define, and identify the relational operators in example expressions.
  • Write Boolean expressions and initialize Boolean variables, and distinguish a Boolean expression from the Boolean data type.
  • Code if-then-else structures and trace the flow of nested-if and else-if structures.
  • Explain fall through in the context of decision control structures.
  • Identify logical operators, use truth tables for and and or, and use not to negate a Boolean value.

1. Control structures

Why programs need decisions

Consider an automated phone system: “Press or say 1 to connect to an account agent; press 2 to troubleshoot your cable service…” If that program ran strictly in sequence, every caller would be asked for a name, connected to an agent, sent to the cable troubleshooter, sent to the Internet troubleshooter, and then disconnected, no matter which option they chose.

The book’s sequential version of the algorithm:

Output "Press or say 1 to connect to an account agent."
Output "Press or say 2 to troubleshoot your cable service."
Output "Press or say 3 to troubleshoot your Internet service."
Output "Press or say 0 to quit."
Ask for customer's name.
Ask for customer's account number.
Provide current account status.
Connect to next available agent.
Connect user to automated cable troubleshooter.
Connect user to automated Internet troubleshooter.
Make sure the user really wants to quit.
Output goodbye message.

Clearly this should not be sequential. A caller with an Internet problem who presses 3 should go directly to the Internet troubleshooter.

Check for understanding: How many distinct branches should this algorithm have? Four, one for each menu option: 1, 2, 3, and 0.

Key terms

  • A control structure alters the sequential execution of statements in a program.
  • A decision control structure alters the sequential flow by branching to specific statements based on a condition or decision.

Decision logic is everywhere

Decision control structures make programs seem intelligent because they respond to user input, and they let programs handle data differently based on its value. Book examples to discuss:

  • Deciding who is eligible to vote based on age and citizenship
  • Determining whether a polynomial has zero, one, or two real roots
  • Assigning a letter grade based on a quiz score
  • Deciding whether to apply a bank service charge based on the account balance
  • Running a furnace or air conditioner based on room temperature
  • Checking whether a number is odd or even with modulo division
  • Offering free shipping based on the amount purchased or VIP status

Quick activity: ask students to state the condition in each example (for instance, age >= 18, number % 2 == 0).

2. The if-then structure

Flowchart and pseudocode

A simple voice system might tell callers to press 1 when they are ready to connect to an agent. In a flowchart, the decision is a diamond containing a question (the condition):

  • When the answer is True, an arrow leads to one or more statements in the conditional block.
  • When the answer is False, the flow bypasses the conditional block.

This logic is an if-then structure, like “If it is raining, I will need an umbrella.” In pseudocode, statements on the True branch are indented:

if the choice is 1 then
    connect user to an agent
show the message "Bye"

The if-then structure is built on a conditional statement, which directs program flow to the correct set of statements when a condition is True. When the user presses 1, the program connects to an agent. When the condition is not True (the user presses 9, for example), the program skips the block and continues sequentially, ending with “Bye.”

Python syntax

if condition:
    statement
if condition:
    statement1
    statement2

Rules and best practices:

  • Place a colon after the condition.
  • Indent every statement that belongs to the if block.
  • Indent all statements in the block the same amount. The standard is four spaces.

C#/JavaScript connection: Python has no braces and no required parentheses around the condition. Indentation is not just style in Python; it is how the language knows which statements belong to the block. Inconsistent indentation causes an IndentationError or, worse, silently changes the logic.

Example: simple voice response

print("Press 1 when you are ready to")
choice = input("connect to an account agent: ")
if choice == "1":
    print("You chose option " + choice)
    print("Connecting you now")
print("Bye")

Sample run:

Press 1 when you are ready to
connect to an account agent: 1
You chose option 1
Connecting you now
Bye
  • Line 2 stores the user’s input. input() always returns a string, so the condition compares against the string "1" (in quotes). You could instead convert with int() and compare with 1.
  • Line 3 is the conditional statement. If it is True, lines 4 and 5 run.
  • Line 6 is not indented, so it runs no matter what.

Check for understanding: What happens if the user presses a number other than 1? The two indented lines are skipped, and the program displays only Bye.

3. Relational operators

== versus =

The condition if choice == "1": uses a double equal sign. == is the equal operator; it checks whether two operands are equal. It is completely different from =, the assignment operator, which stores a value in a variable.

choice = 1
if choice = 0:       # incorrect: SyntaxError
    print("choice is zero")
if choice == 1:      # correct
    print("choice is one")

Using = in a condition produces a syntax error (IDLE and VS Code flag it). This is a helpful difference from C-family languages, where if (x = 0) can sometimes compile and cause a hidden bug.

The full set

A relational operator specifies a comparison between two operands. Operands can be two literals (7 and 9), two variables (airtime and limit), or one variable and one literal (airtime and 1000).

Examples where airtime = 1056:

Operator Description Example Result
== Equal to airtime == 1056 True
airtime == 566 False
!= Not equal to airtime != 1056 False
airtime != 566 True
< Less than airtime < 2000 True
2000 < airtime False
> Greater than airtime > 56 True
56 > airtime False
<= Less than or equal to airtime <= 1056 True
airtime <= 29 False
>= Greater than or equal to airtime >= airtime True
airtime >= 2000 False

Talking points:

  • Watch the order of operands: airtime < 2000 and 2000 < airtime are different questions.
  • The “or equal to” operators are written with the = second: <=, >=. There is no =< or =>.
  • Python does not have JavaScript’s ===. Python’s == never converts types, so "1" == 1 is simply False.

Using != to validate input

Relational operators give flexibility when writing conditions. For example, != can validate input:

Prompt the user to press 1 to connect to an agent
Obtain the user's choice
if the value in choice is not 1
    display an error message
print("Press 1 when you are ready to")
choice = input("connect to an account agent: ")
if choice != "1":
    print("You chose option " + choice + "\n")
    print("Invalid input" + "\n")

Sample run:

Press 1 when you are ready to
connect to an account agent: 9
You chose option 9

Invalid input

The "\n" concatenated to each message adds an extra blank line after it (a review of escape sequences from Lesson 5).

4. Boolean expressions and the Boolean data type

Boolean expressions are formed from relational operators and operands, and they evaluate to True or False. For example, choice != "1" is True when the customer does not select 1 and False when the customer does.

Boolean expressions and Boolean data have something in common: both carry a value of True or False. The difference is in how they are used:

  • A Boolean expression is typically used as part of a conditional statement.
  • The Boolean data type (bool) is used when declaring or assigning a variable.
vip = True

In memory, Boolean variables hold 0 for False and 1 for True. Theoretically a Boolean needs only one bit, but actual storage varies by language.

In Python, True and False must be capitalized. Writing true produces a NameError. (Contrast with C# and JavaScript, which use lowercase true and false.)

vip = True
if vip:
    print("Transferring you to the VIP agent.")

Check for understanding: What is the Boolean variable? What is the conditional statement? What is the Boolean expression?

  • Boolean variable: vip
  • Conditional statement: if vip:
  • Boolean expression: vip (by itself, the variable is the expression)

You could write if vip == True:, but comparing a Boolean variable to True is redundant. The variable already holds True or False, so if vip: is the preferred Python style.

A Boolean variable can also store the result of a Boolean expression:

purchase = 150.00
qualifies = purchase > 100.00    # qualifies holds True

5. The if-then-else structure

Suppose a voice system offers two options: press 1 to connect to an agent, or press 0 to quit. In the flowchart, both the True and False branches contain statements, and the program follows exactly one of them.

A decision coded as two possible paths is an if-then-else structure. Python uses the keyword else for the alternative path.

if condition:
    statement1
    statement2
else:
    statement3
    statement4

Rules and best practices:

  • Place else on its own line, at the same indent level as the if.
  • Put a colon immediately after else, with no condition.
print("Press 1 when you are ready to")
print("connect to an account agent.")
print("Press anything else to quit.")
choice = input()
if choice == "1":
    print("You chose option 1.")
    print("Connecting you now.")
else:
    print("You chose to quit.")
    print("Bye.")

Sample run:

Press 1 when you are ready to
connect to an account agent.
Press anything else to quit.
0
You chose to quit.
Bye.
  • The if block contains two statements; the else block contains two statements.
  • Exactly one block runs. The else block catches every input that is not "1", not just "0".
  • This could be written as two separate if statements, but if-then-else is clearer and evaluates the condition only once.

6. Nested-if structures

Sometimes a program must make a decision within a decision. Example: after the caller chooses the Quit option, the system asks, “Are you sure?” and either disconnects or sends the caller to the help desk. Decisions within decisions are called nested-if structures.

print("Press 1 to connect to an account agent.")
print("Press 0 to quit.")
choice = input()
if choice == "0":
    print("Are you sure you want to quit?")
    sure_thing = input()
    if sure_thing == "y":
        print("Okay, you're sure. Disconnecting.")
    else:
        print("Connecting you to the help desk.")
else:
    print("You chose option 1.")
    print("Connecting you now.")
  • The outer decision (line 4) checks for the Quit option.
  • The inner decision (lines 7 through 10) runs only when the outer condition is True. It uses a second indent level.
  • The final else (line 11) lines up with the outer if, so it pairs with the outer decision.

Check for understanding: Which lines are the inner level of the nested-if? The inner if sure_thing == "y": and its else, plus their indented statements.

Trace practice: have students predict the output for inputs 0 then y, 0 then n, and 1. Note that "Y" (uppercase) goes to the help desk; Lesson 5’s lower() method fixes that: if sure_thing.lower() == "y":.

7. The else-if structure

For more than two options, use an else-if structure. Python combines else and if into one keyword: elif.

if condition1:
    statement1
elif condition2:
    statement2
elif condition3:
    statement3
    statement4
else:
    statement5

Rules and best practices:

  • Begin with an if statement.
  • Use elif for each subsequent condition.
  • Use else for the final “none of the above” case (optional, but recommended for catching bad input).
print("Press 1 to connect to an account agent.")
print("Press 2 to troubleshoot your cable.")
print("Press 3 to troubleshoot your Internet.")
print("Press 0 to quit.")
choice = input()
if choice == "0":
    print("Bye.")
elif choice == "1":
    print("Transferring you to an account agent.")
elif choice == "2":
    print("Connecting you to a cable technician.")
elif choice == "3":
    print("Connecting you to an Internet specialist.")
else:
    print("Invalid input.")

Sample run:

Press 1 to connect to an account agent.
Press 2 to troubleshoot your cable.
Press 3 to troubleshoot your Internet.
Press 0 to quit.
3
Connecting you to an Internet specialist.

Check for understanding: What is the output if a customer enters 2? Enters 7?

  • 2: Connecting you to a cable technician.
  • 7: Invalid input. (no condition matched, so the else runs)

C#/JavaScript connection: elif replaces else if. Python also has a match statement (added in Python 3.10) that resembles switch, but if/elif/else is the standard tool and what this course uses.

8. Fall through

Why use an else-if structure instead of a series of separate if statements?

  • In a series of plain if statements, every condition is evaluated, and each true one runs.
  • In an else-if structure, conditions are evaluated only until one is true. The remaining elif and else branches are skipped.
if choice == 1:
    print("One")
elif choice == 2:
    print("Two")
elif choice <= 2:
    print("Daisy")
else:
    print("Stop")

Ask: What is the output when the user enters 2? Output:

Two

Even though choice <= 2 is also true, that branch never runs because the elif choice == 2 branch already matched.

Fall through means execution continues into the next conditional statement within a structure. If this code fell through, the output would be Two Daisy. Python’s else-if structure has no fall through, so you need to order your conditions carefully: put the most specific conditions first.

Connection: C and JavaScript switch statements fall through unless you add break. C# refuses to compile implicit fall-through between non-empty case sections. Python’s if/elif never falls through.

Contrast demo: rewrite the example as three separate if statements and have students predict the output for 2 (Two, then Daisy).

9. Conditional logical operators

A simple condition such as choice == 1 contains one relational operator. A conditional logical operator combines the outcomes of two or more Boolean expressions. Python’s logical operators are the keywords and, or, and not.

The and operator

Suppose valid menu choices are 0, 1, 2, 3, and 9. Anything greater than 3 other than 9 is invalid:

choice = int(input())
if choice > 3 and choice != 9:
    print("Invalid input.")

Correction to the book’s snippet: the book writes choice = input() and then compares choice > 3. In Python 3 that raises TypeError: '>' not supported between instances of 'str' and 'int', because input() returns a string. Convert with int() before comparing to a number, as shown above.

How Python evaluates the condition when choice contains 7:

  1. Evaluates choice > 3, which is True because 7 > 3.
  2. Evaluates choice != 9, which is True because 7 != 9.
  3. Evaluates True and True, which is True.
  4. The result is True, and the output is Invalid input.

Check for understanding: What happens if choice contains 9? choice > 3 is True, but choice != 9 is False, so True and False is False and nothing is printed.

The and operator requires both conditions to be true. A table summarizing all possible outcomes of a logical operation is a truth table:

choice > 3 choice != 9 choice > 3 and choice != 9
True True True
True False False
False True False
False False False
choice = 9
if choice > 3 and choice != 9:
    print("Invalid input.")
else:
    print("Valid input.")

Output:

Valid input.

The or operator

The or operator requires only one of the conditions to be true. Example: an online store offers free shipping on purchases over $100.00 or to VIP club members. If both conditions are true, the result is still True.

purchase > 100.00 vip purchase > 100.00 or vip
True True True
True False True
False True True
False False False
purchase = 80.00
vip = True
if purchase > 100.00 or vip:
    print("Free shipping!")

Output:

Free shipping!

The purchase is under $100, but vip is True, so the whole expression is True.

Combining operators with parentheses

When one condition uses more than one logical operator, use parentheses so the logic is carried out in the intended order:

if (vip == True and purchase >= 100) or free_shipping_coupon == True:
    print("Free shipping!")

Someone gets free shipping if they are a VIP with a purchase of at least $100, or if they have a coupon. (Following the Boolean-variable advice from Section 4, this can be written more cleanly as if (vip and purchase >= 100) or free_shipping_coupon:.)

Python evaluates not first, then and, then or, but parentheses make the intent clear to anyone reading the code.

The not operator

The not operator is the negation operator. It flips a Boolean value: not True is False, and not False is True. Sometimes it is easier to express a condition in terms of what you do not want to be true.

Check for understanding: Write the Boolean expression for “a coupon can be applied if the item isn’t on clearance and it isn’t jewelry.”

if not clearance and not jewelry:
    print("Coupon applied.")

Symbols vs. keywords

  • Python and corresponds to && in C# and JavaScript.
  • Python or corresponds to the double-pipe operator in C# and JavaScript.
  • Python not corresponds to ! in C# and JavaScript.

Using the C#/JavaScript symbols in Python is a syntax error. Like C# and JavaScript, Python short-circuits: in a and b, if a is False, b is never evaluated; in a or b, if a is True, b is never evaluated.

Preview (not in this module’s reading): Python allows chained comparisons such as 1 <= choice <= 3, which means 1 <= choice and choice <= 3.

Classroom application

  1. Branch count. Give students a menu with five options. Have them draw the flowchart, count the branches, and then write the if/elif/else code.
  2. Assignment vs. equality. Show if score = 100: and have students predict and read the error message, then fix it.
  3. Grade assigner. Ask for a quiz score (use int(input(...))) and print A, B, C, D, or F with an elif chain. Then reverse the order of the conditions (check >= 60 first) and discuss why every passing score becomes a D. This makes the “no fall through, order matters” point concrete.
  4. Odd or even. Use number % 2 == 0 in an if-then-else to classify a user-entered integer.
  5. Are you sure? Extend the nested-if example so that y, Y, yes, and YES all disconnect, using lower() and or.
  6. Truth-table fill-in. Give purchase and vip values and have students fill in the result column for and and or before running the code.

Common misconceptions

  • “= and == are interchangeable.” = assigns; == compares. Using = in a condition is a syntax error in Python.
  • “input() gives me a number.” It always returns a string. Compare to "1", or convert with int() before comparing to 1 or using >/<.
  • “Indentation is just for readability.” In Python it defines the block. Misaligned lines either cause an IndentationError or change which statements are inside the if.
  • “else needs a condition.” else: never has a condition; it catches everything the earlier conditions did not.
  • “Python uses else if.” The keyword is elif.
  • “Every true elif runs.” Only the first true branch runs; the rest are skipped (no fall through).
  • “true and false work.” Python requires True and False.
  • “Use the C# symbols for and/or.” Python uses and, or, and not.
  • “if vip == True: is required.” A Boolean variable can be tested directly: if vip:.
  • “or means exactly one.” or is True when either or both operands are True.

Lesson summary

  • A control structure alters the sequential execution of statements. A decision control structure branches to specific statements based on a condition.
  • Decision control structures include if-then, if-then-else, nested-if, and else-if.
  • Decision structures begin with a conditional statement such as if choice == 1:, ending in a colon, followed by an indented block.
  • Conditional statements use relational operators: ==, !=, >, <, >=, and <=.
  • Use == (equal operator), not = (assignment operator), in conditions.
  • Relational operators and operands form Boolean expressions that evaluate to True or False.
  • Boolean expressions are used in conditions; the Boolean data type is used in declarations and assignments. A Boolean variable can serve as a Boolean expression by itself.
  • else provides the alternative path; elif adds additional conditions.
  • Python’s else-if structure has no fall through: only the first true branch runs.
  • The logical operators and and or build compound conditions, summarized in truth tables; not negates a Boolean value.