Skip to main content

Python Pattern Matching

Composable patterns and regular expressions for Python objects.

Python Pattern Matching is a small, pure-Python library for matching values, destructuring sequences, binding names, applying predicates, and expressing regular-expression-style patterns over sequences of arbitrary Python objects.

Patterns are ordinary runtime values. There are no import hooks, codecs, AST transforms, or special syntax.

pip install patternmatching

Sixty-second tour

Match literals, types, nested sequences, and predicates:

from patternmatching import bind, bound, like, match

message = ["created", "/users/42", 201]

assert match(
    message,
    [
        "created",
        bind.path,
        like(lambda status: 200 <= status < 300, name=None),
    ],
)
assert bound.path == "/users/42"

A type used as a pattern matches its instances. A like(...) pattern applies a callable, or a text regular expression, to the value.

Bindings are also equality constraints when reused:

assert match(("left", "left"), (bind.side, bind.side))
assert bound.side == "left"

assert not match(("left", "right"), (bind.side, bind.side))

Regular expressions for object sequences

The same object patterns compose into regex-like sequence patterns. Repetition, alternatives, exclusion, capturing groups, greediness, and backtracking work on strings, lists, tuples, and other indexable sequences.

from patternmatching import bound, group, match, padding, repeat

events = ["noise", "BEGIN", 1, 2, 3, "END", "tail"]

pattern = (
    padding
    + ["BEGIN"]
    + (int * repeat(min=1)) * group("values")
    + ["END"]
)

assert match(events, pattern)
assert bound.values == [1, 2, 3]

Here padding is a non-greedy repetition of any object. The int pattern matches integer objects, repeat(min=1) requires one or more, and group(...) captures the matching slice.

Sequence patterns match from the beginning and may match a prefix, like re.match. A successful pattern does not inherently require consuming the entire sequence.

Pattern vocabulary

Literals and equality

Literal patterns compare equal to the value:

assert match(1, 1)
assert match("hello", "hello")

Other objects also match by equality when no more specific rule applies.

Types

A class pattern uses isinstance. When the value is itself a class, issubclass is used:

assert match(42, int)
assert match(bool, int)

Sequences

Lists match list patterns, tuples match tuple patterns, and nested patterns are visited recursively:

assert match([1, "two", [3.0]], [int, str, [float]])

Bindings

Any attribute of bind creates a named binding pattern. bind.any matches one value without storing it:

assert match([1, 2, 3], [bind.any, bind.middle, bind.any])
assert bound.middle == 2

Each successful call pushes its bindings onto bound. Attribute and mapping access read the most recent result. bound.pop() discards it and bound.reset() clears all results. bound.reset can also decorate a function to scope the results it creates.

Predicates and text regular expressions

like(pattern, name="match") applies a callable to the value. A falsy result, or a common value/lookup/type error, is a mismatch. A truthy result is bound under name; pass name=None when no result is needed.

When pattern is text, it is passed to re.match:

assert match("item-42", like(r"item-(\d+)"))
assert bound.match.group(1) == "42"

Custom patterns

Pattern objects can implement __match__(matcher, value). Raise patternmatching.Mismatch to reject the value, or return normally to accept it:

import patternmatching


class Between:
    def __init__(self, low, high):
        self.low = low
        self.high = high

    def __match__(self, matcher, value):
        if not self.low <= value <= self.high:
            raise patternmatching.Mismatch


assert patternmatching.match(7, Between(1, 10))

The Matcher class also accepts an ordered collection of matching cases for applications that need to define an entire matching vocabulary.

Sequence pattern operators

  • anyone matches one object.
  • anything matches zero or more objects greedily.
  • something matches one or more objects greedily.
  • padding matches zero or more objects non-greedily.
  • pattern * repeat(min=0, max=inf, greedy=True) repeats a pattern.
  • pattern * maybe matches zero or one occurrence.
  • either(a, b, ...) matches the first successful alternative.
  • exclude(a, b, ...) consumes one object if none of its alternatives match.
  • pattern * group(name) captures the matching slice.
  • left + right concatenates sequence patterns.

Parentheses are useful because multiplication binds more tightly than concatenation:

pattern = ["("] + (int * repeat(min=1)) * group("items") + [")"]

Development

Run the test suite with Nox and uv:

uvx nox -s tests

The test suite includes doctests and a set of object-pattern tests adapted from CPython's regular-expression tests.

License

Python Pattern Matching is copyright 2015–2026 Grant Jenks and licensed under the Apache License, Version 2.0.

Release files for patternmatching 3.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for patternmatching 3.1.0
File Size Uploaded
patternmatching-3.1.0.tar.gz 14.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for patternmatching 3.1.0
File Interpreter ABI Platform
patternmatching-3.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 25.0 kB

Release files / patternmatching-3.1.0.tar.gz

Download URL patternmatching-3.1.0.tar.gz
Size 14.8 kB
Tags Source
SHA-256 checksum
How to use checksums
c864eb57af979993181653a21fceeac16d0ec2599df152b2cbf38f91c0e2375e
BLAKE2b-256 checksum
How to use checksums
376676c6fe9cda989bfe8d1fa55336dcba3c60a96c700380176df646254f9637
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.

Transparency log

Release files / patternmatching-3.1.0-py3-none-any.whl

Download URL patternmatching-3.1.0-py3-none-any.whl
Size 10.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d41e8806efbd07a2d559ed0c156396dc552841f08b15e2b3d3b08dfbd36e433
BLAKE2b-256 checksum
How to use checksums
2398082db6f3453e5054146fe1f9fc4b06fe7dc9aaf51dc3a50be534faf2f494
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.

Transparency log

Release history Release notifications | RSS feed

4.0.0

2 release files

This release

3.1.0 This release

2 release files

3.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page