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 pattern matching.
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).
Pattern Matching Syntax
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 see 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, the corresponding text is returned - Otherwise, it returns “Other value”.
Matching with Data Structures
Pattern matching in Python is particularly useful when used with more complex data structures (like lists, dictionaries, and tuples). Let’s look at some more advanced examples.
Lists and Tuples
In this example, we will see how to recognize patterns in lists or tuples with 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 make a default case if none of the previous ones are met
Dictionaries
We can also apply Pattern Matching to dictionaries, to search for those that meet a certain condition. 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 containing 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
.