The pattern matching mechanism appeared in Python 3.10 under the name Structural Pattern Matching and is implemented using the match-case construct. This tool allows for elegantly and concisely analyzing complex data structures by matching them with patterns.
In many functional languages (like Haskell, Scala), pattern matching has long been regarded as a convenient way to branch logic based on data structure. Python long lacked such a mechanism, relying on chains of if-elif-else or unpacking.
Complex nested data structures (dictionaries, lists, objects) often require multiple checks on types, values, and structure, leading to convoluted code with many conditions.
match-case provides a declarative and readable way to describe different data handling scenarios considering type and structure without an overload of conditions.
def process(event): match event: case {"type": "click", "x": x, "y": y}: return f"Click at ({x}, {y})" case [command, *args]: return f"Command: {command}, args: {args}" case _: return "Unknown event" print(process({"type": "click", "x": 2, "y": 5})) # Click at (2, 5) print(process(["RUN", 1, 2, 3])) # Command: RUN, args: [1, 2, 3]
Does match-case only match by value? No. Matching can occur by structure, type, unpacking collections, and even object properties (if special methods match_args are specified).
Does the order of cases in match matter? Yes. The analysis proceeds top to bottom, the first matching pattern triggers. Subsequent cases are not checked.
Can custom classes be matched? Yes, if the class implements match_args and/or getitem methods. Then pattern matching can extract field values.
class Point: __match_args__ = ("x", "y") def __init__(self, x, y): self.x = x self.y = y def where(obj): match obj: case Point(x, y): return f"Point at {x}, {y}" case _: return "Unknown" print(where(Point(1, 2))) # Point at 1, 2
Pros:
Negative case: Developers used match-case even for simple boolean branches, which only complicated the code. Pros: they learned a new feature. Cons: they lost readability and increased the number of bugs.
Positive case: In an application with a large number of events and nested structures (e.g., a graph parser), match-case helped avoid cumbersome if-elif and centralized parsing. Pros: readability increased, and the number of bugs decreased. Cons: required training the team on the new construct.