Structural Pattern Matching
match/case destructures data by shape — tuples, lists, dicts, classes and guards, not just values.
You met match as a tidy replacement for if/elif. Its real power is structural: each case can describe the shape of the data and pull values out of it in the same step.
Patterns that capture
point = (0, 5)
match point:
case (0, 0):
print('origin')
case (0, y): # matches (0, anything), binds y
print(f'on Y axis at {y}')
case (x, 0):
print(f'on X axis at {x}')
case (x, y):
print(f'at {x}, {y}')
# -> on Y axis at 5The pattern kinds
- Sequence:
[a, b, *rest]matches lists/tuples and captures the tail. - Mapping:
{'type': 'user', 'name': n}matches dicts with those keys. - Class:
Point(x=0, y=y)matches instances and reads attributes. - Guard: add
ifto a case for an extra condition. - Or:
case 'y' | 'yes' | 'true':matches any alternative.
Beware one trap: a bare name like case x: is a capture that matches anything, not a comparison to a variable x. To match against a constant, use a dotted name (case Color.RED:) or a literal.
Example
Loading editor…
Press Run to execute the code.
When to use it
- An event dispatcher uses structural pattern matching to destructure incoming event dicts by their 'type' key.
- A CLI parser matches command tuples like ('move', x, y) to dispatch to the correct handler function.
- A JSON schema validator uses class patterns to confirm that parsed data matches expected dataclass shapes.
More examples
Destructure a tuple with match
Matches tuple shapes and binds their elements to variables in one compact case clause.
def handle(cmd):
match cmd:
case ('move', x, y):
print(f'Move to ({x}, {y})')
case ('fire', angle):
print(f'Fire at {angle} degrees')
case _:
print('Unknown command')
handle(('move', 10, 20)) # Move to (10, 20)
handle(('fire', 45)) # Fire at 45 degreesClass pattern matching
Matches dataclass instances by their type and extracts named attributes in the case clause.
from dataclasses import dataclass
@dataclass
class Click: x: int; y: int
@dataclass
class Keypress: key: str
def dispatch(event):
match event:
case Click(x=x, y=y): print(f'Click at {x},{y}')
case Keypress(key=k): print(f'Key: {k}')
dispatch(Click(100, 200)) # Click at 100,200
dispatch(Keypress('Enter')) # Key: EnterOR patterns and guards
Combines OR patterns to match multiple values and a guard clause to refine the match condition.
def classify(value):
match value:
case 0 | 0.0:
return 'zero'
case int(n) | float(n) if n < 0:
return 'negative'
case int() | float():
return 'positive'
case str():
return 'string'
print(classify(-3)) # negative
print(classify(0.0)) # zero
print(classify('hi')) # string
Discussion