Pattern matching is a technique introduced in Python 3.10 that allows comparing a data structure with a given pattern and executing code based on the pattern match.
Unlike traditional if-else
statements, pattern matching provides a more readable and concise way to handle different cases, especially when working with nested and complex data structures.
Syntax of Pattern Matching
The basic syntax of pattern matching in Python consists of the keyword match
followed by an expression to be compared, and a case
block to define the patterns to match.
Let’s look at a basic example of pattern matching using a simple data structure:
def analyze_data(data):
match data:
case 1:
return "One"
case 2:
return "Two"
case 3:
return "Three"
case _:
return "Other value"
In this example:
- The function
analyze_data
usesmatch
to compare the value ofdata
with the patterns defined in thecase
blocks. - If
data
is equal to 1, 2, or 3, it returns the corresponding text. - Otherwise, it returns “Other value”.
Matching with Data Structures
Pattern matching in Python is especially powerful when used with more complex data structures like lists, dictionaries, and tuples. Let’s see some more advanced examples.
Lists and Tuples
In this example, we’ll see how to recognize patterns in lists or tuples using Pattern Matching.
def analyze_list(lst):
match lst:
case [1, 2, 3]:
return "Case 1: 1 to 3"
case [1, *rest]:
return f"Case 2: Starts with 1 and then {rest}"
case _:
return "Other type of list"
print(analyze_list([1, 2, 3])) # Output: 'Case 1: 1 to 3'
print(analyze_list([1, 4, 5])) # Output: 'Starts with 1 and then [4, 5]'
print(analyze_list([7, 8])) # Output: 'Other type of list'
In this example:
- The pattern
[1, 2, 3]
looks for exactly that list. - The pattern
[1, *rest]
uses the*
operator to capture all remaining elements in a list after a specific element (in this case,1
). - The pattern
_
is a “discard” and is used to create a default case if none of the previous ones are met.
Dictionaries
We can also apply Pattern Matching to dictionaries to look for those that meet certain conditions. For example:
def analyze_dictionary(dictionary):
match dictionary:
case {"name": name, "age": age}:
return f"Case 1: Name: {name}, Age: {age}"
case {"name": name}:
return f"Case 2: Name: {name}"
case _:
return "Other type of dictionary"
print(analyze_dictionary({"name": "Ana", "age": 30}))
# Output: 'Case 1: Name: Ana, Age: 30'
print(analyze_dictionary({"name": "Luis"}))
# Output: 'Case 2: Name: Luis'
print(analyze_dictionary({"city": "Madrid"}))
# Output: Other type of dictionary
Here, the pattern {"name": name, "age": age}
is used to match a dictionary that contains specific keys and capture their values.
Class Patterns
Pattern matching also allows working with class objects and checking if a class instance matches a certain pattern:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def analyze_person(person):
match person:
case Person(name="Ana", age=30):
return "Person Ana, 30 years old"
case Person(name, age):
return f"Person: {name}, Age: {age}"
case _:
return "Other type of object"
person1 = Person("Ana", 30)
person2 = Person("Luis", 25)
print(analyze_person(person1)) # Output: Person Ana, 30 years old
print(analyze_person(person2)) # Output: Person: Luis, Age: 25
In this case, match
is used to check instances of the Person
class and capture the attributes name
and age
.