Python Tutorial › Control Flow › Match Case

Python Match Case

BeginnerLesson 14 of 4710 min read6 runnable examples

match compares one value against a list of patterns and runs the block for the first pattern that fits. It is Python’s answer to the switch statement found in other languages, and it can also pull values out of lists and dictionaries.

Advertisement
In this lesson
  • Replace long elif chains with match
  • Combine values with OR patterns
  • Add conditions with guards
  • Match and unpack lists and dicts

Your first match statement

match was added in Python 3.10. Each case is a pattern. _ is the wildcard: it matches anything, so it works like else.

Python
status_code = 404 match status_code:    case 200:        print("OK")    case 404:        print("Not found")    case 500:        print("Server error")    case _:        print("Unknown status")
Output
Not found

Only the first matching case runs. Unlike C or Java, there is no fall-through and no break needed.

Several values in one case

Use | to mean “or”:

Python
def day_type(day):    match day.lower():        case "saturday" | "sunday":            return "weekend"        case "monday" | "tuesday" | "wednesday" | "thursday" | "friday":            return "weekday"        case _:            return "not a day" for d in ["Sunday", "wednesday", "Funday"]:    print(d, "->", day_type(d))
Output
Sunday -> weekend
wednesday -> weekday
Funday -> not a day

Capture a value and add a guard

A bare name in a pattern captures the value. An if after the pattern is a guard: the case matches only if the guard is true.

Python
def grade(score):    match score:        case n if n >= 90:            return "A"        case n if n >= 75:            return "B"        case n if n >= 0:            return "C or below"        case _:            return "invalid" print(grade(95), grade(80), grade(40), grade(-5))
Output
A B C or below invalid
Tip

For simple range checks like this, if / elif is just as clear. match really shines when you need to look at the shape of the data, as below.

Match sequences

Patterns can describe lists and tuples. Names in the pattern are filled from the matching positions, and *rest collects the remaining items.

Python
def run(command):    match command.split():        case ["quit"]:            return "Bye"        case ["go", direction]:            return f"Going {direction}"        case ["take", first, *others]:            return f"Taking {first} and {len(others)} more"        case []:            return "Say something"        case _:            return f"Unknown command: {command!r}" for c in ["go north", "take key lamp rope", "quit", "", "dance"]:    print(run(c))
Output
Going north
Taking key and 2 more
Bye
Say something
Unknown command: 'dance'

Match dictionaries

A mapping pattern checks that certain keys exist and captures their values. Extra keys are ignored, which makes this ideal for JSON from an API.

Python
events = [    {"type": "click", "x": 10, "y": 20},    {"type": "key", "key": "Enter"},    {"type": "scroll"},] for event in events:    match event:        case {"type": "click", "x": x, "y": y}:            print(f"click at ({x}, {y})")        case {"type": "key", "key": key}:            print(f"key {key} pressed")        case {"type": other}:            print(f"unhandled event {other}")
Output
click at (10, 20)
key Enter pressed
unhandled event scroll

Match by type

int(), str() and other class names in a pattern check the type:

Python
def describe(value):    match value:        case bool():            return "a boolean"        case int() | float():            return "a number"        case str() if value == "":            return "an empty string"        case str():            return "a string"        case list():            return f"a list of {len(value)}"        case _:            return "something else" for v in [True, 3, 2.5, "", "hi", [1, 2], None]:    print(repr(v), "is", describe(v))
Output
True is a boolean
3 is a number
2.5 is a number
'' is an empty string
'hi' is a string
[1, 2] is a list of 2
None is something else
Note

bool() is checked before int() because True is also an int. As with elif, put the more specific case first.

Check your understanding

Predict the output

point = (0, 5)match point:    case (0, 0):        print("origin")    case (0, y):        print(f"on the y axis at {y}")    case (x, 0):        print(f"on the x axis at {x}")    case _:        print("somewhere else")

Quick quiz

1. Which Python version introduced match?

2. What does case _: do?

3. How do you match “y” or “yes” in one case?

Exercise: calculator

Write calc(a, op, b) with match that supports +, -, * and /, returns “cannot divide by zero” for division by 0, and “unknown operator” otherwise.

Input
calc(6, "*", 7), calc(9, "/", 0), calc(9, "/", 3), calc(1, "^", 2)
Expected output
42 cannot divide by zero 3.0 unknown operator
Hint 1

A guard like case "/" if b == 0: must come before case "/":.

Program Practice

The if-else programs are a great place to practise match: try rewriting a few solutions with it.

Python match case FAQ

Does Python have a switch case statement?

Yes, since Python 3.10 the match statement does everything a switch does, plus matching on the structure of lists, tuples, dicts and objects.

Do I need break in Python match case?

No. Only the first matching case runs and there is no fall-through.

What is the default case in Python match?

case _: matches any value, so it acts as the default.

Is match faster than if elif?

Not meaningfully. Choose match when it makes the code clearer, especially when unpacking structured data.

Leave a Comment