Chapters
Python114 chapters

Control flowChapter 44 of 114

Match

Structural pattern matching, and where it beats a chain of elif.

The basic form

match compares a value against a series of patterns and runs the first one that fits:

Python
command = "start"

match command:
    case "start":
        print("Starting")
    case "stop":
        print("Stopping")
    case _:
        print("Unknown command")

Output

Starting

case _ is the catch-all, equivalent to else. Without it, an unmatched value simply falls through and nothing happens.

Several values in one case

Python
for key in ["q", "x", "a"]:
    match key:
        case "q" | "x":
            print(key, "-> quit")
        case _:
            print(key, "-> ignored")

Output

q -> quit
x -> quit
a -> ignored

The | means "or". There is no fall-through between cases, so no break is needed.

Matching structure, not just values

This is what match is actually for, and where a chain of elif gets ugly. Patterns can destructure the value:

Python
points = [(0, 0), (5, 0), (0, 3), (2, 4)]

for point in points:
    match point:
        case (0, 0):
            print("origin")
        case (x, 0):
            print(f"on the x axis at {x}")
        case (0, y):
            print(f"on the y axis at {y}")
        case (x, y):
            print(f"somewhere at {x},{y}")

Output

origin
on the x axis at 5
on the y axis at 3
somewhere at 2,4

Names in a pattern are bound, not compared. case (x, 0) matches any pair whose second item is zero, and x becomes the first item.

Matching dictionaries

Handling JSON-shaped data is where this earns its place:

Python
events = [
    {"type": "click", "x": 10, "y": 20},
    {"type": "key", "value": "a"},
    {"type": "scroll"},
]

for event in events:
    match event:
        case {"type": "click", "x": x, "y": y}:
            print(f"click at {x},{y}")
        case {"type": "key", "value": value}:
            print(f"key {value}")
        case {"type": kind}:
            print(f"unhandled: {kind}")

Output

click at 10,20
key a
unhandled: scroll

A dictionary pattern matches on the keys it names and ignores any others, which is what makes it robust against extra fields.

Guards

An if on a case adds a condition the pattern alone cannot express:

Python
for value in [5, 50, -3]:
    match value:
        case n if n < 0:
            print(n, "negative")
        case n if n > 10:
            print(n, "large")
        case n:
            print(n, "small")

Output

5 small
50 large
-3 negative

Matching classes

Python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

match Point(0, 7):
    case Point(x=0, y=y):
        print("on the y axis at", y)
    case Point():
        print("somewhere else")

Output

on the y axis at 7

When to use it

match needs Python 3.10 or newer. Reach for it when you are picking apart the shape of data — tuples, dictionaries, objects. For a simple value check, an if/elif chain is shorter and every reader already knows it.

Test yourself

2 questions

In 'case (x, 0):', what does x do?

Show the answer

Binds to the first item of any pair whose second item is 0 — Bare names in a pattern bind rather than compare, which is why 'case limit:' matches everything.

What does a dictionary pattern do about keys it does not name?

Show the answer

Ignores them — That is what makes match robust against extra fields in JSON-shaped data.

Next chapter

While Loops

Repeat while a condition holds, and make sure it eventually stops.