Control Flow
Python expresses branching with if/elif/else, structural matching with match/case, and iteration with for and while. Loop else clauses and short-circuit boolean operators are idioms worth learning early.
Busca en todas las páginas de la documentación
Python expresses branching with if/elif/else, structural matching with match/case, and iteration with for and while. Loop else clauses and short-circuit boolean operators are idioms worth learning early.
for index, item in enumerate(["a", "b", "c"], start=1):
if item == "b":
continue
print(index, item)
match status:
case 200:
print("ok")
case 404 | 410:
print("missing")
case code if 500 <= code < 600:
print("server error")When to reach for this:
matchbreak)zipfrom dataclasses import dataclass
@dataclass
class Event:
kind: str
payload: dict[str, object]
def handle(event: Event) -> str:
match event:
case Event(kind="user.created", payload={"id": int(uid), "email": str(email)}):
return f"provision {uid} for {email}"
case Event(kind="user.deleted", payload={"id": int(uid)}):
return f"cleanup {uid}"
case Event(kind=k):
return f"ignored {k}"
case _:
return "unknown"
def find_first_negative(nums: list[int]) -> int | None:
for n in nums:
if n < 0:
return n
else:
return None # no break occurred
def main() -> None:
events = [
Event("user.created", {"id": 1, "email": "a@example.com"}),
Event("order.placed", {"id": 99}),
]
for ev in events:
print(handle(ev))
print(find_first_negative([1, 2, 3]))
if __name__ == "__main__":
main()What this demonstrates:
match binds variables (uid, email) while matching dict structurefor/else returns a sentinel when no break firescontinue skips to the next iteration without exiting the loopif - Objects implement __bool__ or __len__.a and b evaluates b only if a is truthy; a or b skips b if a is truthy.for calls iter() then repeated next() until StopIteration.for else - runs when loop ends without break.| Pattern | Example | Matches |
|---|---|---|
| Literal | case 404: | Exact value |
| OR | case 401 | 403: | Either value |
| Guard | case int(n) if n > 0: | Pattern + condition |
| Sequence | case [x, y, *rest]: | List/tuple length and shape |
| Mapping | case {"id": int(i)}: | Dict keys and types |
# walrus := assigns inside expressions (3.8+)
if (line := input()) == "quit":
pass
# zip strict=True (3.10+) raises on unequal lengths
for a, b in zip(xs, ys, strict=True):
...| or shared logic.else runs when no break, not on falsy condition. Fix: Comment intent or refactor to functions.[0] is truthy because non-empty. Fix: Compare lengths or values explicitly when needed.| Alternative | Use When | Don't Use When |
|---|---|---|
if/elif chain | Simple scalar comparisons | Deeply nested JSON shapes |
match/case | Structural destructuring | Two-branch boolean only |
| Dict dispatch | Many callables keyed by str | Need destructuring |
filter/map | Functional transforms | Side effects per item |
When branching on structure - typed dict keys, tuple arity, or class attributes. Stick to if for simple booleans.
The else block runs after the loop completes without hitting break. Useful for search loops.
Use a flag, extract to a function with return, or in 3.11+ structured exception patterns sparingly.
Class patterns use isinstance semantics; literals use equality. Sequence patterns match structure and length.
and/or stop evaluating once the result is determined - use for guard clauses like obj and obj.method().
enumerate(items, start=0) - cleaner than manual counter variables.
Yes - case MyClass(attr=value): matches instances with attributes. Dataclasses work well here.
continue jumps to next iteration. pass is a no-op placeholder in syntax-required blocks.
Include case None: or use guards. Combine with type hints and narrowing in static checkers.
Rare in application code. for/else for search is more idiomatic; prefer functions over clever loop else.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Revisado por Chris St. John·Última actualización: 19 jul 2026