The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Match a literalcase 200:View examples
Capture the subjectcase value:View examples
Ignore the subjectcase _:View examples
Match a fixed sequencecase [command, target]:View examples
Capture remaining itemscase [head, *middle, tail]:View examples
Match a command prefixcase ['deploy', environment, *flags]:View examples
Require mapping keyscase {'event': 'login', 'user': user}:View examples
Capture extra mapping entriescase {'event': kind, **metadata}:View examples
Match class attributes positionallycase Point(0, y):View examples
Match class attributes by namecase Point(x=x, y=0):View examples
Match alternativescase 401 | 403:View examples
Capture across alternativescase ('get', path) | ('delete', path):View examples
Keep a matched valuecase (401 | 403) as status:View examples
Add a guardcase {'score': score} if score >= 80:View examples
Match a symbolic constantcase Status.READY:View examples
Match nested structurescase {'type': 'move', 'point': [x, y]}:View examples

Structural pattern matching, available since Python 3.10, selects the first case whose pattern matches a subject and whose optional guard is true. Patterns describe shape and can bind parts of the subject; they are not ordinary Boolean conditions or assignment targets. Use match when several branches decompose the same structured value, and keep conventional if/elif logic when branches are primarily unrelated predicates.

Step by step

Detailed examples

01

Order specific cases before captures and wildcards

Cases are attempted from top to bottom and only the first qualifying block runs. Literal patterns test numbers and strings with equality, while None, True, and False use identity. A bare name is a capture pattern, not a constant lookup, and always succeeds; an unguarded capture or wildcard is therefore irrefutable and must be the final case. Successful bindings remain available after the match statement, but code must never depend on partial bindings from a failed match because their persistence is intentionally unspecified.

Classify response statuses in case order
def classify(status):
    match status:
        case 200:
            return 'ok'
        case 400 | 404:
            return 'client error'
        case _:
            return 'other'

for status in (200, 404, 503):
    print(status, classify(status))
Output
200 ok
404 client error
503 other
Back to quick reference ↑
02

Decompose sequences by length and position

Sequence patterns work with recognized sequence types, including list, tuple, range, and collections.abc.Sequence implementations, but not arbitrary iterators. They deliberately exclude str, bytes, and bytearray, preventing text from being split unexpectedly. Square and round pattern syntax behave alike. A fixed pattern requires an exact length, while one starred subpattern accepts any number of items and captures them in a list.

Parse tokenized commands
def parse(tokens):
    match tokens:
        case ['show']:
            return 'show all'
        case ['show', name]:
            return f'show {name}'
        case ['deploy', environment, *flags]:
            return f'deploy {environment} with {len(flags)} flags'
        case _:
            return 'invalid'

print(parse(['show', 'cache']))
print(parse(['deploy', 'prod', '--force', '--wait']))
print(parse('show'))
Output
show cache
deploy prod with 2 flags
invalid
Back to quick reference ↑
03

Select required mapping fields without requiring an exact shape

A mapping pattern succeeds when every listed key exists and its value matches; unrelated keys are ignored rather than causing failure. Add one final **rest capture when the remaining entries matter. Matching uses the mapping's two-argument get behavior rather than __missing__, so defaultdict and similar implicit insertion hooks are not triggered. Duplicate literal keys are a syntax error, and **_ is not permitted.

Route event dictionaries and retain metadata
def route(event):
    match event:
        case {'event': 'login', 'user': user, **metadata}:
            return f'login {user}; extras={sorted(metadata)}'
        case {'event': kind}:
            return f'event {kind}'
        case _:
            return 'invalid'

print(route({'event': 'login', 'user': 'Ada', 'ip': '127.0.0.1'}))
print(route({'event': 'logout', 'user': 'Ada'}))
print(route(['login', 'Ada']))
Output
login Ada; extras=['ip']
event logout
invalid
Back to quick reference ↑
04

Match typed objects through class attributes

A class pattern first applies isinstance to the subject. Keyword subpatterns read explicitly named attributes; missing attributes make the pattern fail, while other exceptions propagate. Positional subpatterns are translated through the class's __match_args__ tuple. Dataclasses and named tuples populate __match_args__ automatically, but keyword patterns are more resilient when a public constructor or field order may change.

Match dataclass points by position and keyword
from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

def location(point):
    match point:
        case Point(0, 0):
            return 'origin'
        case Point(x=x, y=0):
            return f'x-axis at {x}'
        case Point(x, y):
            return f'point {x},{y}'
        case _:
            return 'not a point'

print(location(Point(0, 0)))
print(location(Point(7, 0)))
print(location(Point(2, 3)))
Output
origin
x-axis at 7
point 2,3
Back to quick reference ↑
05

Combine alternatives and retain the complete match

An OR pattern tries alternatives from left to right and stops at the first success. Every alternative must bind exactly the same set of names, which keeps later code unambiguous. An AS pattern binds the complete value after its left-hand pattern succeeds; parentheses clarify when AS applies to an entire OR pattern. These forms can remove duplicated case bodies while keeping supported shapes explicit.

Share routing logic across methods and statuses
def describe(request):
    match request:
        case ('get', path) | ('delete', path):
            return f'resource {path}'
        case ('status', (401 | 403) as code):
            return f'denied {code}'
        case _:
            return 'unsupported'

print(describe(('get', '/health')))
print(describe(('delete', '/cache')))
print(describe(('status', 403)))
Output
resource /health
resource /cache
denied 403
Back to quick reference ↑
06

Use guards for constraints that shape alone cannot express

A guard runs only after its pattern has succeeded, so captured names are available in the guard expression. If the guard is false, matching continues with the next case; if it raises, the exception propagates. Guards are evaluated in case order until a block is selected. Keep them short and free of mutations because their side effects can make control flow difficult to reason about.

Apply score thresholds after extraction
def grade(record):
    match record:
        case {'name': name, 'score': score} if score >= 80:
            return f'{name}: pass'
        case {'name': name, 'score': score} if 0 <= score < 80:
            return f'{name}: retry'
        case {'name': name, 'score': _}:
            return f'{name}: invalid score'
        case _:
            return 'invalid record'

print(grade({'name': 'Mina', 'score': 91}))
print(grade({'name': 'Sol', 'score': 72}))
print(grade({'name': 'Ivo', 'score': -1}))
Output
Mina: pass
Sol: retry
Ivo: invalid score
Back to quick reference ↑
07

Use qualified names for constants in value patterns

A dotted name such as Status.READY is a value pattern: Python looks it up and compares the subject with that value. A bare READY would instead capture any subject and make following unguarded cases unreachable. Enums and namespaced constants make this distinction visible. Repeated value lookups within one match execution may be cached, so properties or descriptors used as constants should not rely on a precise lookup count.

Match enum members without accidental captures
from enum import Enum

class Status(Enum):
    READY = 'ready'
    BUSY = 'busy'

def message(status):
    match status:
        case Status.READY:
            return 'start work'
        case Status.BUSY:
            return 'wait'
        case _:
            return 'unknown'

print(message(Status.READY))
print(message(Status.BUSY))
print(message('ready'))
Output
start work
wait
unknown
Back to quick reference ↑
08

Compose patterns to validate and unpack nested data

Patterns compose recursively, so one case can describe a mapping whose field contains a sequence or class instance. This is useful at a trusted parsing boundary after basic decoding, but it is not full schema validation: extra mapping keys are accepted, types only receive the checks expressed by subpatterns, and no matching case raises nothing automatically. Include a deliberate fallback that rejects or reports malformed input.

Interpret nested drawing commands
def interpret(message):
    match message:
        case {'type': 'move', 'point': [int(x), int(y)]}:
            return f'move to {x},{y}'
        case {'type': 'label', 'text': str(text)}:
            return f'label {text}'
        case _:
            return 'invalid command'

print(interpret({'type': 'move', 'point': [4, 9]}))
print(interpret({'type': 'move', 'point': ['4', 9]}))
print(interpret({'type': 'label', 'text': 'home'}))
Output
move to 4,9
invalid command
label home
Back to quick reference ↑

Local code tester

Route structured messages

Change the messages, add a guarded case, or introduce a dataclass pattern to explore first-match behavior.

Runs in your browser
Output
Press Run to load Python locally.

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Python Software FoundationThe match statement — Python Language Referencedocs.python.org
  2. Python Software FoundationPEP 634 — Structural Pattern Matching: Specificationpeps.python.org
  3. Python Software FoundationPEP 635 — Structural Pattern Matching: Motivation and Rationalepeps.python.org
  4. Python Software FoundationPEP 636 — Structural Pattern Matching: Tutorialpeps.python.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback