Skip to content

Python Flow Control

This article covers Python’s conditional statements, loops, and comprehensions, including the structural pattern matching (match/case) introduced in Python 3.10.

if Statements

age = 19
is_member = True

if age >= 18 and is_member:
    print("Welcome, adult member!")
elif age >= 18:
    print("Welcome, general visitor!")
elif age >= 13:
    print("Minor user — some features are restricted")
else:
    print("Does not meet age requirements")
  • Indentation must be consistent; the official recommendation is 4 spaces.
  • if branches are evaluated top-to-bottom; once a branch matches, the rest are skipped.
  • Nesting depth should not exceed 3 levels — deeper nesting should be refactored into functions.

Ternary Expression

x, y = 3, 5
smaller = x if x < y else y   # 3

# Nested ternary (poor readability — use with caution)
grade = "A" if score >= 90 else ("B" if score >= 80 else "C")

match/case (Structural Pattern Matching, Python 3.10+)

match/case is a more powerful pattern-matching syntax than if/elif. It supports value matching, destructuring, and type matching:

# Basic value matching
status = 404

match status:
    case 200:
        print("OK")
    case 404:
        print("Not Found")
    case 500:
        print("Internal Server Error")
    case _:
        print(f"Unknown status code: {status}")
# Sequence destructuring
command = ("move", 10, 20)

match command:
    case ("quit",):
        print("Quit")
    case ("move", x, y):
        print(f"Move to ({x}, {y})")
    case ("say", message):
        print(f"Say: {message}")
    case _:
        print("Unknown command")
# Class matching (works with __match_args__)
from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

def describe(point: Point) -> str:
    match point:
        case Point(x=0, y=0):
            return "Origin"
        case Point(x=0, y=y):
            return f"On the Y-axis, y={y}"
        case Point(x=x, y=0):
            return f"On the X-axis, x={x}"
        case Point(x=x, y=y):
            return f"Point ({x}, {y})"

# Guard condition
match point:
    case Point(x, y) if x == y:
        print(f"On the diagonal, coordinate {x}")
    case Point(x, y):
        print("Not on the diagonal")

while Loops

count = 0
while count < 5:
    print(count)
    count += 1

# while-else: the else block runs when the loop exits normally (without break)
attempts = 0
while attempts < 3:
    password = input("Enter password: ")
    if password == "secret":
        print("Login successful")
        break
    attempts += 1
else:
    print("Too many incorrect attempts — account locked")

Simplifying while with the Walrus Operator (Python 3.8+)

# Traditional approach
line = input()
while line:
    process(line)
    line = input()

# Walrus operator approach
while line := input("> "):
    process(line)

for Loops

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

# With index: enumerate
for i, fruit in enumerate(fruits, start=1):
    print(f"{i}. {fruit}")

# Iterate over multiple sequences simultaneously: zip
names = ["Alice", "Bob", "Charlie"]
scores = [90, 85, 92]
for name, score in zip(names, scores):
    print(f"{name}: {score}")

# range
for i in range(10):          # 0–9
    print(i)

for i in range(1, 10, 2):   # 1, 3, 5, 7, 9
    print(i)

# for-else: the else block runs when the loop exits normally (without break)
for i in range(5):
    if i == 3:
        break
else:
    print("Loop completed normally")   # Not executed when break fires

break / continue

# break: immediately exit the entire loop
for i in range(10):
    if i == 5:
        break
    print(i)    # 0 1 2 3 4

# continue: skip the current iteration and move to the next
for i in range(10):
    if i % 2 == 0:
        continue
    print(i)    # 1 3 5 7 9

Comprehensions

Comprehensions are Python syntactic sugar for concisely building collections. There are four common forms:

List Comprehensions

# [expression for variable in iterable if condition]
squares = [x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

evens = [x for x in range(20) if x % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Nested (flatten a 2D matrix)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Dictionary Comprehensions

# {key_expr: value_expr for variable in iterable}
squares = {x: x ** 2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# Invert a dictionary's keys and values
d = {"a": 1, "b": 2}
reversed_d = {v: k for k, v in d.items()}
# {1: "a", 2: "b"}

Set Comprehensions

# {expression for variable in iterable if condition}
unique_chars = {c.lower() for c in "Hello World" if c != " "}
# {'h', 'e', 'l', 'o', 'w', 'r', 'd'}

Generator Expressions

# Parentheses: does not build the entire sequence immediately; generates values on demand (memory-efficient)
gen = (x ** 2 for x in range(1_000_000))
print(next(gen))   # 0
print(next(gen))   # 1

# Commonly passed to functions that accept iterables
total = sum(x ** 2 for x in range(100))
Comprehensions are concise, but readability always comes first. When nesting exceeds two levels or the logic becomes complex, switch to a regular for loop.
Last updated on