Control Structures

Introduction

Programs rarely execute linearly from top to bottom. Control structures allow you to make decisions, repeat actions, and change the flow of execution based on conditions.

Learning Objectives

By the end of this reading, you will be able to:

  • Write conditional statements (if/else)
  • Use different types of loops (for, while)
  • Control loop execution with break and continue
  • Nest control structures appropriately
  • Choose the right control structure for a problem

1. Sequential Execution

By default, code executes line by line:

print("First")
print("Second")
print("Third")
# Output: First, Second, Third

Control structures change this flow.


2. Conditional Statements

Basic If Statement

Execute code only if a condition is true:

age = 20

if age >= 18:
    print("You are an adult")

Key points:

  • Condition must evaluate to a boolean (or be "truthy"/"falsy")
  • Indentation defines the code block
  • Colon : after the condition

If-Else

Handle both true and false cases:

temperature = 35

if temperature > 30:
    print("It's hot!")
else:
    print("It's not too hot")

If-Elif-Else

Multiple conditions:

score = 85

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
elif score >= 60:
    grade = "D"
else:
    grade = "F"

print(f"Your grade: {grade}")  # B

Important: Only the first matching condition executes.

x = 15

if x > 5:
    print("Greater than 5")    # This prints
elif x > 10:
    print("Greater than 10")   # This doesn't (even though true)

Conditional Expressions (Ternary)

One-line conditionals:

age = 20
status = "adult" if age >= 18 else "minor"
print(status)  # "adult"

# Equivalent to:
if age >= 18:
    status = "adult"
else:
    status = "minor"

Truthiness

Python evaluates these as False:

  • False
  • None
  • 0 (zero of any numeric type)
  • "" (empty string)
  • [] (empty list)
  • {} (empty dict)
  • set() (empty set)

Everything else is True:

name = ""
if name:
    print(f"Hello, {name}")
else:
    print("No name provided")  # This runs

items = [1, 2, 3]
if items:
    print("List has items")    # This runs

3. Comparison and Logical Operators

Comparison Operators

x = 5
y = 10

x == y    # Equal: False
x != y    # Not equal: True
x < y     # Less than: True
x > y     # Greater than: False
x <= y    # Less than or equal: True
x >= y    # Greater than or equal: False

Logical Operators

a = True
b = False

a and b   # False (both must be true)
a or b    # True (at least one true)
not a     # False (inverts)

# Combining conditions
age = 25
income = 50000

if age >= 18 and income >= 30000:
    print("Eligible for loan")

# Chained comparisons
x = 5
if 0 < x < 10:     # Same as: 0 < x and x < 10
    print("x is between 0 and 10")

Short-Circuit Evaluation

Python stops evaluating as soon as the result is determined:

# 'and' stops at first False
False and expensive_function()  # expensive_function never called

# 'or' stops at first True
True or expensive_function()    # expensive_function never called

# Practical use:
if user and user.is_active:     # Avoids error if user is None
    process(user)

4. Loops

For Loops

Iterate over a sequence:

# Iterate over a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

# Iterate over a string
for char in "Hello":
    print(char)

# Iterate over a range
for i in range(5):        # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 6):     # 2, 3, 4, 5
    print(i)

for i in range(0, 10, 2): # 0, 2, 4, 6, 8 (step of 2)
    print(i)

While Loops

Repeat while a condition is true:

count = 0
while count < 5:
    print(count)
    count += 1
# Output: 0, 1, 2, 3, 4

# Waiting for input
password = ""
while password != "secret":
    password = input("Enter password: ")
print("Access granted!")

Danger: Infinite loops

# This runs forever!
while True:
    print("Forever...")

# Common mistake - forgetting to update condition
x = 0
while x < 5:
    print(x)
    # Forgot: x += 1

Loop Control

break: Exit the loop immediately

for i in range(10):
    if i == 5:
        break
    print(i)
# Output: 0, 1, 2, 3, 4

continue: Skip to next iteration

for i in range(5):
    if i == 2:
        continue
    print(i)
# Output: 0, 1, 3, 4 (skips 2)

else on loops: Runs if loop completes without break

for i in range(5):
    if i == 10:  # Never true
        break
else:
    print("Loop completed normally")  # This prints

for i in range(5):
    if i == 3:
        break
else:
    print("Loop completed normally")  # This doesn't print

Nested Loops

# Multiplication table
for i in range(1, 4):
    for j in range(1, 4):
        print(f"{i} × {j} = {i*j}")
    print("---")

# Output:
# 1 × 1 = 1
# 1 × 2 = 2
# 1 × 3 = 3
# ---
# 2 × 1 = 2
# ... etc

5. Iterating with Indices

enumerate()

Get both index and value:

fruits = ["apple", "banana", "cherry"]

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")
# 0: apple
# 1: banana
# 2: cherry

# Start from different index
for index, fruit in enumerate(fruits, start=1):
    print(f"{index}: {fruit}")
# 1: apple
# 2: banana
# 3: cherry

zip()

Iterate over multiple sequences:

names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]

for name, age in zip(names, ages):
    print(f"{name} is {age}")
# Alice is 25
# Bob is 30
# Charlie is 35

Iterating Dictionaries

person = {"name": "Alice", "age": 25, "city": "Boston"}

# Keys
for key in person:
    print(key)

# Values
for value in person.values():
    print(value)

# Both
for key, value in person.items():
    print(f"{key}: {value}")

6. List Comprehensions

Concise way to create lists:

# Traditional loop
squares = []
for x in range(5):
    squares.append(x ** 2)

# List comprehension
squares = [x ** 2 for x in range(5)]
# [0, 1, 4, 9, 16]

# With condition
evens = [x for x in range(10) if x % 2 == 0]
# [0, 2, 4, 6, 8]

# With transformation
words = ["hello", "world"]
upper = [w.upper() for w in words]
# ["HELLO", "WORLD"]

Other Comprehensions

# Set comprehension
unique_lengths = {len(word) for word in ["hi", "hello", "hey"]}
# {2, 5, 3}

# Dictionary comprehension
squares_dict = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# Generator expression (memory-efficient)
sum_of_squares = sum(x**2 for x in range(1000000))

7. Match Statement (Python 3.10+)

Pattern matching for complex conditions:

def handle_command(command):
    match command.split():
        case ["quit"]:
            return "Goodbye!"
        case ["load", filename]:
            return f"Loading {filename}"
        case ["save", filename]:
            return f"Saving {filename}"
        case ["move", x, y]:
            return f"Moving to ({x}, {y})"
        case _:
            return "Unknown command"

print(handle_command("load data.txt"))  # Loading data.txt
print(handle_command("move 10 20"))     # Moving to (10, 20)

Matching with Guards

def categorize_number(n):
    match n:
        case 0:
            return "zero"
        case n if n < 0:
            return "negative"
        case n if n % 2 == 0:
            return "positive even"
        case _:
            return "positive odd"

8. Common Patterns

Finding an Item

def find_first_negative(numbers):
    for num in numbers:
        if num < 0:
            return num
    return None

result = find_first_negative([1, 2, -3, 4])
print(result)  # -3

Counting

def count_vowels(text):
    count = 0
    for char in text.lower():
        if char in "aeiou":
            count += 1
    return count

# Or with sum and comprehension
def count_vowels(text):
    return sum(1 for char in text.lower() if char in "aeiou")

Accumulating

def total_price(items):
    total = 0
    for item in items:
        total += item["price"]
    return total

# Or with sum
def total_price(items):
    return sum(item["price"] for item in items)

Filtering

def get_adults(people):
    adults = []
    for person in people:
        if person["age"] >= 18:
            adults.append(person)
    return adults

# Or with comprehension
def get_adults(people):
    return [p for p in people if p["age"] >= 18]

# Or with filter
def get_adults(people):
    return list(filter(lambda p: p["age"] >= 18, people))

Transforming

def double_all(numbers):
    result = []
    for n in numbers:
        result.append(n * 2)
    return result

# Or with comprehension
def double_all(numbers):
    return [n * 2 for n in numbers]

# Or with map
def double_all(numbers):
    return list(map(lambda n: n * 2, numbers))

9. Best Practices

Avoid Deep Nesting

# Hard to read
if condition1:
    if condition2:
        if condition3:
            do_something()

# Better - guard clauses
if not condition1:
    return
if not condition2:
    return
if not condition3:
    return
do_something()

Prefer For Over While When Possible

# Unclear when it ends
i = 0
while i < len(items):
    process(items[i])
    i += 1

# Clear and concise
for item in items:
    process(item)

Use Meaningful Loop Variables

# Unclear
for x in data:
    print(x)

# Clear
for user in users:
    print(user)

for row_index, row in enumerate(matrix):
    for col_index, value in enumerate(row):
        print(f"[{row_index}][{col_index}] = {value}")

Exercises

Basic

  1. Write a program that prints "Fizz" for multiples of 3, "Buzz" for multiples of 5, and "FizzBuzz" for multiples of both, for numbers 1-20.

  2. Given a list of numbers, print only the positive ones:

numbers = [1, -2, 3, -4, 5, -6]
  1. Use a while loop to find the first power of 2 greater than 1000.

Intermediate

  1. Write a program that finds all prime numbers between 2 and 50.

  2. Create a number guessing game:

    • Computer picks a random number 1-100
    • User guesses until correct
    • Give "higher" or "lower" hints
import random
target = random.randint(1, 100)
# Your code here
  1. Given a list of words, create a dictionary mapping each word to its length:
words = ["apple", "banana", "cherry", "date"]
# Expected: {"apple": 5, "banana": 6, "cherry": 6, "date": 4}

Advanced

  1. Write a program that prints a multiplication table (1-10) formatted nicely.

  2. Implement a simple calculator that:

    • Continuously prompts for expressions like "5 + 3"
    • Supports +, -, *, /
    • Quits when user types "quit"
  3. Using nested loops, print this pattern:

*
**
***
****
*****
****
***
**
*

Summary

  • Conditionals (if/elif/else) make decisions
  • For loops iterate over sequences
  • While loops repeat until a condition is false
  • break exits loops; continue skips iterations
  • List comprehensions provide concise list creation
  • Match statements (3.10+) handle complex pattern matching
  • Choose the right structure: for when you know iterations, while when you don't

Next Reading

Functions and Scope →