Structural Pattern Matching in Python (match/case)
match looks like a switch statement, but it's more powerful: it can check the shape of data and pull values out of it in one step.
Literals and alternatives
def http_message(status: int) -> str:
match status:
case 200 | 201:
return "OK"
case 404:
return "Not found"
case 500 | 502 | 503:
return "Server error"
case _:
return "Unknown"
Sequences: parsing commands
def handle(command: str):
match command.split():
case ["help"]:
show_help()
case ["add", item]:
add(item)
case ["add", item, qty] if qty.isdigit():
add(item, int(qty))
case ["remove", *items]:
for i in items:
remove(i)
case _:
print("Unknown command")
Mappings: handling JSON events
def process(event: dict):
match event:
case {"type": "payment.succeeded", "data": {"amount": int(amount), "currency": cur}}:
record_payment(amount, cur)
case {"type": "payment.failed", "data": {"reason": reason}}:
notify_failure(reason)
case {"type": str(kind)}:
log.info("ignoring event %s", kind)
Mapping patterns ignore extra keys, which is exactly what you want for webhook payloads.
Class patterns
from dataclasses import dataclass
@dataclass
class Circle:
radius: float
@dataclass
class Rect:
w: float
h: float
def area(shape) -> float:
match shape:
case Circle(radius=r):
return 3.14159 * r * r
case Rect(w, h) if w == h:
return w * w # a square
case Rect(w, h):
return w * h
When to use it
- Branching on the structure of data: parsed commands, JSON events, AST nodes, message types.
- Stick with
if/eliffor simple value comparisons or boolean conditions. - Bare names in a pattern capture values; to compare against a constant, use a dotted name like
Status.ACTIVE.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.