Structural Pattern Matching in Python (match/case)

A
Author
03 Jul, 2026 1 min read 848 views

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/elif for 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.

Leave a comment

Comments are reviewed before they appear.