Python Match

Learn about the match statement in Python 3.10+ - a powerful pattern matching feature.

Python Match Statement

The match statement was introduced in Python 3.10. It provides a way to compare a value against several patterns and execute code based on which pattern matches.

The match statement is similar to switch statements in other programming languages, but much more powerful due to pattern matching capabilities.

Basic Example

def check_value(x):
    match x:
        case 1:
            return "One"
        case 2:
            return "Two"
        case 3:
            return "Three"
        case _:
            return "Something else"

print(check_value(2))  # Output: Two
print(check_value(5))  # Output: Something else

Basic Syntax

The basic syntax of a match statement consists of:

  • The match keyword followed by an expression
  • One or more case clauses with patterns
  • An optional wildcard case using _

Example

status = 404

match status:
    case 200:
        print("OK")
    case 404:
        print("Not Found")
    case 500:
        print("Internal Server Error")
    case _:
        print("Unknown status")

Pattern Matching with Multiple Values

You can match against multiple values in a single case:

Example

def check_grade(grade):
    match grade:
        case 'A' | 'B':
            return "Excellent"
        case 'C' | 'D':
            return "Good"
        case 'F':
            return "Fail"
        case _:
            return "Invalid grade"

print(check_grade('A'))  # Output: Excellent
print(check_grade('C'))  # Output: Good

Pattern Matching with Conditions

You can add conditions to patterns using the if keyword:

Example

def categorize_number(x):
    match x:
        case n if n < 0:
            return "Negative"
        case 0:
            return "Zero"
        case n if n > 100:
            return "Large positive"
        case n if n > 0:
            return "Small positive"

print(categorize_number(-5))   # Output: Negative
print(categorize_number(150))  # Output: Large positive

Matching Lists and Tuples

Match statements can destructure sequences like lists and tuples:

Example

def analyze_point(point):
    match point:
        case [0, 0]:
            return "Origin"
        case [0, y]:
            return f"On Y-axis at {y}"
        case [x, 0]:
            return f"On X-axis at {x}"
        case [x, y]:
            return f"Point at ({x}, {y})"
        case _:
            return "Not a 2D point"

print(analyze_point([0, 0]))    # Output: Origin
print(analyze_point([3, 0]))    # Output: On X-axis at 3
print(analyze_point([2, 5]))    # Output: Point at (2, 5)

Matching Dictionaries

You can match against dictionary patterns:

Example

def process_request(request):
    match request:
        case {"action": "get", "resource": resource}:
            return f"Getting {resource}"
        case {"action": "post", "resource": resource, "data": data}:
            return f"Posting to {resource}: {data}"
        case {"action": "delete", "resource": resource}:
            return f"Deleting {resource}"
        case _:
            return "Invalid request"

req1 = {"action": "get", "resource": "users"}
req2 = {"action": "post", "resource": "posts", "data": "Hello World"}

print(process_request(req1))  # Output: Getting users
print(process_request(req2))  # Output: Posting to posts: Hello World

Matching Objects and Classes

Match statements can work with custom classes and objects:

Example

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def describe_point(point):
    match point:
        case Point(x=0, y=0):
            return "Origin point"
        case Point(x=0, y=y):
            return f"Point on Y-axis at y={y}"
        case Point(x=x, y=0):
            return f"Point on X-axis at x={x}"
        case Point(x=x, y=y) if x == y:
            return f"Point on diagonal at ({x}, {y})"
        case Point(x=x, y=y):
            return f"Point at ({x}, {y})"

p1 = Point(0, 0)
p2 = Point(3, 3)
p3 = Point(5, 2)

print(describe_point(p1))  # Output: Origin point
print(describe_point(p2))  # Output: Point on diagonal at (3, 3)
print(describe_point(p3))  # Output: Point at (5, 2)

Capturing Values

You can capture parts of the matched pattern into variables:

Example

def process_data(data):
    match data:
        case [first, *rest]:
            return f"First: {first}, Rest: {rest}"
        case {"name": name, "age": age, **others}:
            return f"Person: {name}, Age: {age}, Other info: {others}"
        case str() as text if len(text) > 10:
            return f"Long string: {text[:10]}..."
        case _:
            return "Unknown data format"

print(process_data([1, 2, 3, 4]))  
# Output: First: 1, Rest: [2, 3, 4]

print(process_data({"name": "Alice", "age": 30, "city": "NYC"}))  
# Output: Person: Alice, Age: 30, Other info: {'city': 'NYC'}

print(process_data("This is a very long string"))  
# Output: Long string: This is a ...

Practical Example: Calculator

Here's a practical example of using match for a simple calculator:

Example

def calculate(operation):
    match operation:
        case ("add", x, y):
            return x + y
        case ("subtract", x, y):
            return x - y
        case ("multiply", x, y):
            return x * y
        case ("divide", x, y) if y != 0:
            return x / y
        case ("divide", x, 0):
            return "Error: Division by zero"
        case ("power", x, y):
            return x ** y
        case _:
            return "Unknown operation"

print(calculate(("add", 5, 3)))        # Output: 8
print(calculate(("divide", 10, 2)))    # Output: 5.0
print(calculate(("divide", 10, 0)))    # Output: Error: Division by zero
print(calculate(("power", 2, 3)))      # Output: 8

Match vs If-Elif-Else

While match statements are powerful, they're not always necessary. Here's when to use each:

Use Match When:

  • Pattern matching complex data structures
  • Destructuring sequences or objects
  • Multiple conditions on the same value
  • Working with structured data

Use If-Elif-Else When:

  • Simple boolean conditions
  • Comparing different variables
  • Complex logical expressions
  • Backward compatibility (Python < 3.10)