Frontend Labs
⋯

4. Control flow and pattern matching

4.1 if, for, while

status = 503
if status < 300:
    kind = "ok"
elif status < 500:
    kind = "client error"
else:
    kind = "server error"

kind = "ok" if status < 300 else "error"     # conditional expression

for i in range(3):                  # 0, 1, 2
    print(i)

for i, host in enumerate(["web1", "web2"], start=1):
    print(i, host)

for name, port in zip(["http", "https"], [80, 443], strict=True):
    print(name, port)               # strict=True: raise if lengths differ

retries = 3
while retries > 0:
    retries -= 1

for in Python is always a "for each" over an iterable (Ch 13). There is no C-style for (i = 0; ...); use range or, better, iterate directly over the collection.

4.2 break, continue, and for ... else

def find_free_port(used: set[int]) -> int:
    for port in range(8000, 8100):
        if port in used:
            continue
        break
    else:                             # runs only if the loop did NOT break
        raise RuntimeError("no free port")
    return port

print(find_free_port({8000, 8001}))   # 8002

4.3 The walrus operator :=

:= assigns inside an expression. Use it where it removes a duplicated call:

import re

for line in ["user=ada id=7", "noise", "user=linus id=9"]:
    if (m := re.search(r"user=(\w+)", line)):
        print(m.group(1))

4.4 Structural pattern matching: match

match (3.10+) is not a C switch. It destructures data by shape, like Rust's match:

def handle(event: dict) -> str:
    match event:
        case {"type": "click", "x": int(x), "y": int(y)}:
            return f"click at {x},{y}"
        case {"type": "key", "key": "q" | "Q"}:
            return "quit"
        case {"type": "key", "key": str(k)} if len(k) == 1:
            return f"key {k}"
        case {"type": t}:
            return f"unknown event {t}"
        case _:
            return "malformed"

print(handle({"type": "click", "x": 10, "y": 20}))   # click at 10,20
print(handle({"type": "key", "key": "Q"}))           # quit
print(handle({"type": "scroll"}))                    # unknown event scroll
print(handle([]))                                    # malformed

It matches sequences, mappings, class instances, literals, and alternatives (|), with guards (if). It shines on parsed JSON, command lines, and ASTs. Two traps: a bare name in a pattern binds a variable instead of comparing (case code: matches anything), and Python does not check that you covered every case. Use dotted names (case Status.OK:) to compare against constants.

match ["deploy", "web", "--force"]:
    case ["deploy", service, *flags]:
        print(service, flags)          # web ['--force']
    case ["rollback", service]:
        print("rollback", service)

Generated from real-life-python-guide.md · 8 Oct 2026 16:36