Skip to content

RESOURCES / BLOG

How does the match statement work in Python?

You have probably seen code snippets using Python’s match and case and wondered when to use them compared to if or dictionaries of callables. In community threads, developers often ask how structural pattern matching works in real code, what patterns exist, and how to avoid common pitfalls.

Hi all,
I am learning Python and keep seeing structural pattern matching. How does the match statement work in Python? What patterns can I match on, how do guards work, and what are the common gotchas? Sample code appreciated.

Python’s match statement provides structural pattern matching, introduced in 3.10. It lets you concisely branch on the shape and content of data rather than only on values. It works especially well with nested dicts, sequences, and dataclasses.

def handle_status(code):
    match code:
        case 200 | 201:
            return "OK"
        case 400:
            return "Bad Request"
        case 404:
            return "Not Found"
        case _:
            return "Unknown"Code language: JavaScript (javascript)

Match statements are an alternative to the traditional if/else loops, allowing code to execute when specific parameters are met. Each case is checked against the input (in this example, code), and the first one that matches will be executed

  • _ is the default case, and should always be at the end of the match statement.
  • The pipe operator | is used as an “or” operation. Both 200 or 201 will pass, returning “OK”.
def classify_point(p):
    match p:
        case [x, y]:
            return f"2D point: {x},{y}"
        case [x, y, z]:
            return f"3D point: {x},{y},{z}"
        case _:
            return "Not a point"

def read_headers(headers):
    match headers:
        case {"content-type": ctype, "content-length": length}:
            return f"{ctype}, {length} bytes"
        case {"content-type": ctype}:
            return f"{ctype}, length unknown"
        case _:
            return "No content-type"Code language: JavaScript (javascript)
from dataclasses import dataclass

@dataclass
class Event:
    type: str
    payload: dict

def handle_event(evt):
    match evt:
        case Event(type="upload", payload={"format": fmt, "size": s}):
            return f"Upload of {fmt} with size {s}"
        case Event(type="delete", payload={"id": asset_id}):
            return f"Delete {asset_id}"
        case _:
            return "Unhandled event"
def parity(n):
    match n:
        case int() if n % 2 == 0:
            return "even"
        case int():
            return "odd"
        case _:
            return "not an int"Code language: JavaScript (javascript)

Guards are boolean expressions after a pattern using if. If the pattern matches but the guard fails, matching continues to the next case.

  • Name capture vs constants: Bare names capture values. To match a constant, qualify it or use literals.
from enum import Enum
class Color(Enum):
    RED = "red"
    BLUE = "blue"

def describe(c):
    match c:
        case Color.RED:
            return "red"
        case Color.BLUE:
            return "blue"
        case _:
            return "other"
  • Order matters: Put specific patterns before general ones to avoid unreachable cases.
  • Pattern shape must match: [x, y] will not match a tuple of three items or a dict.
  • Version requirement: Match statements are only supported in Python 3.10 and later.
  • Parsing loosely structured payloads such as webhooks and API responses.
  • Routing based on file metadata or media formats.
  • Replacing long chains of nested if statements.

If you routinely process images in Python scripts, this pairs nicely with media workflows. For example, you can decide how to save, convert, or optimize based on content-type or file extension.

After you have a working pattern matcher, you can integrate it with delivery. For example, generate different transformation URLs based on the detected format and use Cloudinary to serve the result efficiently. If you are building URLs, see the concept of an image URL, or explore developer-friendly utilities on Cloudinary Tools.

# Example: route media handling with match, then build a delivery URL
def build_delivery(public_id, info):
    match info:
        case {"format": "webp", "width": w} if w > 1200:
            # Convert to JPEG and resize for broad compatibility
            return f"https://res.cloudinary.com/demo/image/upload/c_fill,w_1200,f_jpg/{public_id}.jpg"
        case {"format": "heic"}:
            # Convert HEIC to JPEG on delivery
            return f"https://res.cloudinary.com/demo/image/upload/f_jpg/{public_id}.jpg"
        case {"format": "png"}:
            # Optimize PNG with smart resizing
            return f"https://res.cloudinary.com/demo/image/upload/c_scale,w_800/{public_id}.png"
        case _:
            # Default passthrough
            return f"https://res.cloudinary.com/demo/image/upload/{public_id}"Code language: PHP (php)

This approach keeps your Python logic clean while delegating heavy lifting to a CDN-backed transformation layer. You can expand the pattern to include thumbnails, watermarks, or responsive breakpoints by adding more cases.

  • Match statements provide structural pattern matching for values, sequences, mappings, and classes.
  • Use guards for additional conditions and put specific patterns before general ones.
  • Avoid bare names for constants, prefer qualified names or literals.
  • Great for routing and parsing tasks. Combine with URL based delivery to streamline media pipelines.

Ready to build smarter media flows with clean Python branching and fast delivery? Create your free Cloudinary account and start optimizing today.

Start Using Cloudinary

Sign up for our free plan and start creating stunning visual experiences in minutes.

Sign Up for Free