Python match-case: Cleaner Alternative to if-elif Chains
Problem
Handling API responses often leads to long if-elif chains.
def handle_response(response):
if response['status'] == 200:
return process_data(response['data'])
elif response['status'] == 404:
return None
elif response['status'] == 401 or response['status'] == 403:
raise AuthError()
elif response['status'] >= 500:
raise ServerError()
else:
raise UnknownError(response['status'])
Add a few more conditions and it becomes hard to read.
Solution
Python 3.10+’s match-case makes this much cleaner.
def handle_response(response):
match response:
case {'status': 200, 'data': data}:
return process_data(data)
case {'status': 404}:
return None
case {'status': 401 | 403}:
raise AuthError()
case {'status': status} if status >= 500:
raise ServerError()
case _:
raise UnknownError(response['status'])
The key feature is automatic destructuring. 'data': data extracts and binds the value in one step.
It works with class instances too:
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def describe(point):
match point:
case Point(x=0, y=0):
return "origin"
case Point(x=0, y=y):
return f"on Y-axis ({y})"
case Point(x=x, y=0):
return f"on X-axis ({x})"
case Point(x=x, y=y) if x == y:
return f"on diagonal ({x})"
case _:
return f"general ({point.x}, {point.y})"
Key Points
match-caseis structural pattern matching, not just value comparison- Use
|to combine multiple patterns into one case - Guard clauses with
ifallow additional filtering _is the wildcard pattern, matching anything (works likeelse)- Requires Python 3.10+