Exploring Python's New Structural Pattern Matching (PEP 634)
Master Python's match-case statement with real-world examples and advanced techniques
Introduction
Python 3.10 introduced structural pattern matching (match-case
statements), a powerful way to simplify conditional logic and improve code readability. Inspired by switch-case statements in other languages, structural pattern matching extends Python’s capabilities to match complex data structures like tuples, lists, dictionaries, and custom objects.
In this guide, we’ll explore PEP 634, learn how match-case
works, and see real-world use cases with advanced techniques.
Why Use Structural Pattern Matching?
✅ Improves readability compared to nested if-elif-else
chains
✅ Supports complex data structures like lists, tuples, and dicts
✅ Enables powerful pattern-based dispatching
✅ Optimized for performance in Python’s internals
1. Basic Syntax of match-case
Here’s the simplest form of structural pattern matching:
def http_status(code):
match code:
case 200:
return "OK"
case 404:
return "Not Found"
case 500:
return "Server Error"
case _:
return "Unknown Status"
print(http_status(200)) # OK
print(http_status(404)) # Not Found
print(http_status(503)) # Unknown Status
✔ Uses case _: as a default case, similar to else
in if-elif-else
statements.
2. Matching Tuples and Lists
Pattern matching extends beyond simple values—it works with tuples and lists:
def process_coordinates(point):
match point:
case (0, 0):
return "Origin"
case (x, 0):
return f"X-axis at {x}"
case (0, y):
return f"Y-axis at {y}"
case (x, y):
return f"Point at ({x}, {y})"
case _:
return "Invalid input"
print(process_coordinates((10, 0))) # X-axis at 10
print(process_coordinates((0, 20))) # Y-axis at 20
print(process_coordinates((5, 7))) # Point at (5, 7)
✔ Unpacks values into variables (x, y
) directly inside the match-case
.
3. Matching Dictionaries
You can match dictionaries with key-value patterns:
def identify_user(user):
match user:
case {"role": "admin", "name": name}:
return f"Admin: {name}"
case {"role": "guest"}:
return "Guest User"
case {"role": role}:
return f"User Role: {role}"
case _:
return "Unknown User"
print(identify_user({"role": "admin", "name": "Alice"})) # Admin: Alice
print(identify_user({"role": "guest"})) # Guest User
print(identify_user({"role": "editor"})) # User Role: editor
✔ Extracts dictionary values dynamically using {"key": variable}
syntax.
4. Matching Custom Objects
match-case
can work with custom objects using __match_args__
:
class User:
__match_args__ = ("name", "role")
def __init__(self, name, role):
self.name = name
self.role = role
def check_user(user):
match user:
case User(name, "admin"):
return f"Admin: {name}"
case User(name, role):
return f"User: {name}, Role: {role}"
case _:
return "Unknown User"
u1 = User("Alice", "admin")
u2 = User("Bob", "editor")
print(check_user(u1)) # Admin: Alice
print(check_user(u2)) # User: Bob, Role: editor
✔ Uses __match_args__
to define matchable attributes in the class.
5. Guard Conditions in match-case
You can add conditional checks inside cases:
def categorize_number(n):
match n:
case n if n % 2 == 0:
return "Even number"
case n if n % 2 != 0:
return "Odd number"
case _:
return "Not a number"
print(categorize_number(10)) # Even number
print(categorize_number(7)) # Odd number
✔ Uses case value if condition:
to filter matches dynamically.
6. Real-World Use Case: Parsing API Responses
Pattern matching is great for handling API responses:
def process_api_response(response):
match response:
case {"status": 200, "data": data}:
return f"Success: {data}"
case {"status": 404}:
return "Error: Not Found"
case {"status": 500, "error": msg}:
return f"Server Error: {msg}"
case _:
return "Unknown Response"
response = {"status": 200, "data": {"user": "Alice"}}
print(process_api_response(response)) # Success: {'user': 'Alice'}
✔ Extracts structured data without excessive if-else
checks.
Best Practices for Using match-case
✔ Use structured matching for better readability
✔ Always include a wildcard case (_
) to handle unexpected inputs
✔ Use guards (case value if condition:
) to add extra logic
✔ Prefer dictionary matching for handling structured data
✔ Leverage custom objects to match class instances cleanly
Conclusion
Python’s structural pattern matching (PEP 634) provides a powerful, expressive, and efficient way to handle conditional logic. Whether working with tuples, lists, dictionaries, or objects, match-case
improves readability and reduces complex branching logic.
🚀 Start using pattern matching today and write cleaner, more maintainable Python code!