Python > Evolving Python > Python Versions > New Features in Recent Python Versions
Structural Pattern Matching in Python 3.10
Python 3.10 introduced structural pattern matching, a powerful feature that allows you to match the structure of data against patterns. This is similar to switch statements in other languages but much more expressive. It can handle different types of data, including sequences, mappings, and class instances. It drastically improves code readability when dealing with complex conditional logic based on data structure.
Basic Example: Matching a Point
This example defines a function process_point
that takes a tuple (representing a point) as input. The match
statement then compares the input tuple against several case
patterns. If a pattern matches, the code block associated with that case
is executed. The _
is a wildcard that matches anything, serving as a default case.
def process_point(point):
match point:
case (0, 0): # Matching a tuple with two 0s
print("Origin")
case (x, 0): # Matching a tuple where the second element is 0
print(f"x={x}, on the x-axis")
case (0, y): # Matching a tuple where the first element is 0
print(f"y={y}, on the y-axis")
case (x, y): # Matching any other tuple with two elements
print(f"x={x}, y={y}")
case _:
print("Not a point")
process_point((0, 0))
process_point((5, 0))
process_point((0, 3))
process_point((1, 2))
process_point(5)
Matching Data Classes
This demonstrates pattern matching with data classes. We define a Color
data class with red
, green
, and blue
attributes. The match
statement checks the attributes of a Color
object. Note the use of if
clauses within the case
statements for more complex conditions (guard conditions).
from dataclasses import dataclass
@dataclass
class Color:
red: int
green: int
blue: int
def describe_color(color):
match color:
case Color(red=255, green=0, blue=0): # Exact match
print("Red")
case Color(red=r, green=0, blue=b): # Partial match, capturing values
print(f"Shade of red with blue component {b} and red component {r}")
case Color(red=r, green=g, blue=b) if r == g == b:
print("Gray color")
case Color(red=r, green=g, blue=b): # Generic match
print(f"RGB: {r}, {g}, {b}")
color1 = Color(255, 0, 0)
color2 = Color(200, 0, 50)
color3 = Color(128, 128, 128)
color4 = Color(10, 20, 30)
describe_color(color1)
describe_color(color2)
describe_color(color3)
describe_color(color4)
Concepts Behind the Snippet
Structural pattern matching deconstructs data to match against different patterns. These patterns can be literals, variables, sequences, or object attributes. The match
keyword initiates the matching process, and the case
keyword defines the individual patterns to check. The wildcard _
can be used as a catch-all. Guard clauses (if
conditions within a case
) enable additional filtering.
Real-Life Use Case
Pattern matching is incredibly useful when parsing complex data formats like JSON, XML, or network protocols. Imagine you're building an API that receives different types of messages. Pattern matching can elegantly handle the different message structures and route them to the appropriate handlers.
Best Practices
Always include a default case
(using _
) to handle unexpected data structures. Order your case
statements from most specific to least specific. Use guard clauses judiciously to avoid overly complex patterns. Consider using pattern matching when you find yourself writing deeply nested if-elif-else
statements based on data structure.
When to use them
Use structural pattern matching when you need to handle multiple possible data structures or types in a clear and concise way. It improves readability compared to nested if-else statements, especially when dealing with complex data.
Interview Tip
Be prepared to explain the benefits of structural pattern matching over traditional if-else chains. Demonstrate your understanding of different pattern types (literals, variables, sequences, objects) and guard clauses.
FAQ
-
What is the underscore '_' in a match statement?
The underscore '_' is a wildcard. It matches anything and is typically used as the default case in a match statement. -
Can I use pattern matching with custom classes that are not data classes?
Yes, you can. However, you'll need to define a__match_args__
attribute in your class. This attribute specifies the order in which the class's attributes should be matched. See the Python documentation for more details.