match Statements

Python · Lesson 14 of 56 6 min read Updated

When one value can be one of many things, a long if/elif chain gets repetitive. Python's match statement, added in Python 3.10, compares a value against a list of patterns and runs the first one that fits. It can do what a "switch" does in other languages, and much more: it can also look inside lists and dictionaries and pull values out of them.

In this lesson you will match simple values, combine options, capture parts of lists and dictionaries, check types with class patterns, add extra conditions with guards, and avoid the one mistake that catches almost everyone.

Matching literal values

The simplest patterns are literals: fixed values such as numbers and strings. Python checks each case from top to bottom and runs the first one that matches.

PythonRun it yourself
coach = "3A"

match coach:
    case "1A":
        print("First AC")
    case "2A":
        print("AC 2-tier")
    case "3A" | "3E":
        print("AC 3-tier")
    case "SL":
        print("Sleeper")
    case _:
        print("Unknown coach code")
Output
AC 3-tier

Two pattern features appear here:

  • | means "or": "3A" | "3E" matches either code.
  • _ is the wildcard. It matches anything, so case _: works like else. Put it last.

Only one case runs, and there is no "fall through" to the next case as in C or JavaScript, so you never need break. If no case matches and there is no case _:, nothing happens.

Sequence patterns

A pattern written like a list matches a sequence (a list or tuple) with the same shape, and a plain name inside it captures the value at that position. *rest captures any number of remaining items.

The for loop below runs the match once for each command; you will learn loops in for Loops.

PythonRun it yourself
commands = ["go north", "pick up lamp", "drop key coin", "quit", "dance"]

for text in commands:
    match text.split():
        case ["go", direction]:
            print("Moving", direction)
        case ["pick", "up", item]:
            print("Picked up", item)
        case ["drop", *items]:
            print("Dropped", ", ".join(items))
        case ["quit" | "exit"]:
            print("Bye!")
        case _:
            print("I don't understand:", text)
Output
Moving north
Picked up lamp
Dropped key, coin
Bye!
I don't understand: dance

["go", direction] matches a two-item list whose first item is "go", and stores the second item in direction. Imagine writing the same thing with if, len() and indexes: it would take three times as many lines. Note that strings are not treated as sequences here, so case [a, b]: never matches the string "ab".

Mapping patterns

A pattern written like a dictionary matches a mapping (such as a dict) that has those keys. Extra keys in the data are ignored, which makes this perfect for data from forms and web APIs.

PythonRun it yourself
payment = {"method": "upi", "amount": 499, "upi_id": "priya@okbank"}

match payment:
    case {"method": "upi", "upi_id": upi_id, "amount": amount}:
        print(f"UPI payment of ₹{amount} from {upi_id}")
    case {"method": "card", "amount": amount}:
        print(f"Card payment of ₹{amount}")
    case {"method": "cash"}:
        print("Cash payment")
    case _:
        print("Invalid payment")
Output
UPI payment of ₹499 from priya@okbank

The first case needs "method" to be exactly "upi" and needs the keys "upi_id" and "amount" to exist; their values are captured. Change "method" to "cash" and run it again. You will learn about dictionaries in Dictionaries.

Guards: an extra condition

Add if condition after a pattern to make a guard. The case runs only if the pattern matches and the guard is true. If the guard is false, Python moves on to the next case.

PythonRun it yourself
order = {"item": "samosa", "qty": 40}

match order:
    case {"item": item, "qty": qty} if qty >= 25:
        print(f"Bulk order: {qty} x {item}, call the kitchen")
    case {"item": item, "qty": qty} if qty > 0:
        print(f"Normal order: {qty} x {item}")
    case _:
        print("Empty or invalid order")
Output
Bulk order: 40 x samosa, call the kitchen

Class patterns

A class pattern looks like a call: int(), str(), float(). It matches values of that type. With a name inside the brackets, str(text), it also captures the value. The word as captures whatever matched a larger pattern.

PythonRun it yourself
value = 3.5

match value:
    case bool():
        print("A Boolean:", value)
    case int() | float() as number:
        print("A number, doubled:", number * 2)
    case str(text):
        print("Some text:", text.upper())
    case None:
        print("No value")
    case _:
        print("Something else")
Output
A number, doubled: 7.0

bool() comes first on purpose: bool is a subclass of int, so True would otherwise match int(). Class patterns also work with your own classes, where you match attributes by name. This example uses a dataclass, which you will meet in Dataclasses & Enums:

PythonRun it yourself
from dataclasses import dataclass

@dataclass
class Order:
    item: str
    qty: int

order = Order("tea", 2)

match order:
    case Order(item="tea", qty=qty):
        print(f"{qty} cups of chai")
    case Order(item=item, qty=qty):
        print(f"{qty} x {item}")
Output
2 cups of chai

Common mistakes

  • Using a bare name as a constant. If you write case RED: where RED = "red" is a variable, Python does not compare with it. A bare name is a capture pattern: it matches anything and stores the value in RED. Python even refuses to run such code when more cases follow, with SyntaxError: name capture 'RED' makes remaining patterns unreachable. Use a literal (case "red":) or a dotted name such as Colour.RED from an enum.
  • Putting case _: first. The wildcard matches everything, so later cases would never run.
  • Using match for simple true or false checks. if/else is clearer for one condition; match shines when there are many shapes or values.

match and case are soft keywords: they act as keywords only in this statement, so old code with a variable named match still works.

Key points

  • match value: tries each case from top to bottom and runs only the first one that matches.
  • Literal patterns match fixed values; | combines options; _ matches anything.
  • Sequence patterns like ["go", direction] and [first, *rest] check a list's shape and capture items.
  • Mapping patterns like {"method": "upi", "amount": amount} check keys and ignore extra keys.
  • Class patterns like int(), str(text) and Order(item=item) check types and attributes.
  • A guard case pattern if condition: adds an extra test; bare names capture, they never compare.

Exercise

Write a match statement for a food delivery app. The variable event is a tuple. Handle these shapes: ("placed", order_id) prints "Order 101 placed", ("delivered", order_id, minutes) prints a thank-you message when minutes is 30 or less and an apology otherwise, and ("cancelled", order_id, reason) prints the reason. Anything else prints "Unknown event". Test it with event = ("delivered", 101, 42).

Show solution
Python
event = ("delivered", 101, 42)

match event:
    case ("placed", order_id):
        print(f"Order {order_id} placed")
    case ("delivered", order_id, minutes) if minutes <= 30:
        print(f"Order {order_id} delivered in {minutes} minutes. Thank you!")
    case ("delivered", order_id, minutes):
        print(f"Sorry, order {order_id} took {minutes} minutes")
    case ("cancelled", order_id, reason):
        print(f"Order {order_id} cancelled: {reason}")
    case _:
        print("Unknown event")
Output
Sorry, order 101 took 42 minutes

Sequence patterns work with tuples as well as lists. The guard sends fast deliveries to the first "delivered" case, and everything else falls through to the second one.

Quick Quiz

1. What does case _: do in a match statement?

2. Which pattern matches the list ["drop", "key", "coin"] and captures the last two items?

3. With RED = "red", what does case RED: do?

4. When does a case with a guard, case [x, y] if x > y:, run?

Learn Python with a mentor

Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call