match and case

Matching a value against patterns rather than testing it with a chain of conditions - including patterns that destructure as they match.

Overview

The tidy version of an if-chain

match status:
    case 200:
        return "ok"
    case 500 | 502 | 503:
        return "server error"
    case _:
        return "unhandled"

| groups alternatives, _ is the default. The first matching case wins and the rest are skipped — there is no fall-through and no break.

If this were all match did it would be barely worth the keyword, and the page prints an if-chain beside it that agrees on every input.

match_basics.py

match_basics.py Python 3
Output

                    

match_structure.py

match_structure.py Python 3
Output

                    

Worth knowing

case _: is the default. Without it, no match simply falls through and nothing happens.
| matches several literals in one case.
Patterns bind as they match: case {"x": x} pulls x out for you.
A bare name matches everything and binds. Use case Colour.RED or case 200, not a lone variable.

match and case: A Practical Guide

match tests a value against patterns rather than conditions. For plain literals it is a tidier if-chain; for structured data it is something an if-chain cannot do at all, because the pattern takes the value apart while matching it.

What it actually adds

case {"type": "click", "x": x, "y": y}:

This matches a dictionary that has a type of "click", and in the same breath binds x and y to the values it found. One line replaces a type check, two key checks and two lookups — and it cannot go out of step with itself the way that sequence can.

The same applies to sequences:

case [first, *rest]:

matches any list and splits it into head and tail as it goes.

Guards

A pattern can carry a condition:

case int() if n < 0:

The pattern narrows the shape, the guard narrows the value. Together they express "an integer, and a negative one" in the place where you are already looking.

The trap: a bare name matches everything

case status:

This does not compare against a variable called status. A bare name is a capture pattern: it matches anything and binds the name. It is the single most common match mistake, and it fails quietly — the first case swallows every value.

To compare against a constant, use a dotted name (case Status.OK:), a literal, or a guard.

When to use it

For two or three literal comparisons, if is shorter and everyone reads it. Reach for match when you are inspecting the *shape* of data — parsed JSON, events, commands, ASTs — where the alternative is a stack of isinstance checks and key lookups. That is the job it was added for.

match needs Python 3.10 or newer.

Check yourself

0 of 3

Answer without scrolling back up.

  1. What does a bare `case status:` do?

  2. What happens when no case matches and there is no `case _`?

  3. `case {"type": "click", "x": x}` does what beyond matching?

Cheat sheet

match and case

match tests a value against patterns rather than conditions. For plain literals it is a tidier if-chain; for structured data it is something an if-chain cannot do at all, because the pattern takes the value apart while matching it.

PYTHON · vizlearn.in/python/match_and_case.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.