The match-case statement, introduced in Python 3.10, is used to perform pattern matching. It allows a value to be compared against multiple patterns and executes the code block associated with the first match. It provides a more organized alternative to long if-elif-else statements when handling multiple conditions.
def check_number(x):
match x:
case 10:
print("It's 10")
case 20:
print("It's 20")
case _:
print("It's neither 10 nor 20")
check_number(10)
check_number(30)
Output
It's 10 It's neither 10 nor 20
Explanation:
- match x: starts the pattern-matching block using the value of x.
- case 10: executes when x is equal to 10.
- case 20: executes when x is equal to 20.
- case _: is the default case and runs when no other pattern matches.
- check_number(10) matches case 10, while check_number(30) matches the wildcard _ case.
Syntax
The match statement evaluates a value and compares it against one or more case patterns. When a matching pattern is found, the corresponding code block is executed.
match subject:
case pattern1:
# Code block if pattern1 matches
case pattern2:
# Code block if pattern2 matches
case _:
# Code block if no pattern matches
- match subject: specifies the value that will be checked against different patterns.
- case pattern: defines a pattern to compare with the subject.
- case _: acts as a fallback case and runs when none of the other patterns match.
Matching Constant Values
Constant patterns allow you to compare a value against specific predefined values and execute different code blocks based on the match. This is useful when a program needs to handle a fixed set of known values.
def greet(person):
match person:
case "A":
print("Hello, A!")
case "B":
print("Hello, B!")
case _:
print("Hello, stranger!")
greet("A")
greet("B")
Output
Hello, A! Hello, B!
Explanation:
- case "A" matches when person is "A".
- case "B" matches when person is "B".
- case _ acts as the default case when no match is found.
Matching Multiple Values with OR (|)
The | operator lets you group multiple patterns into a single case block. The matched code runs when the value matches any one of the specified patterns.
def num_check(x):
match x:
case 10 | 20 | 30:
print(f"Matched: {x}")
case _:
print("No match found")
num_check(10)
num_check(20)
num_check(25)
Output
Matched: 10 Matched: 20 No match found
Explanation:
- 10 | 20 | 30 matches any of the three values.
- If x is not one of these values, the wildcard _ handles the case.
Adding Conditions with Guards
Guards allow you to add extra checks to a pattern using the if keyword. A case is executed only when the value matches the pattern and the specified condition evaluates to True.
def num_check(x):
match x:
case n if n > 0:
print("Positive number")
case n if n < 0:
print("Negative number")
case _:
print("Zero")
num_check(15)
num_check(-8)
num_check(0)
Output
Positive number Negative number Zero
Explanation:
- case n if n > 0 matches positive numbers.
- case n if n < 0 matches negative numbers.
- _ handles all remaining values.
Matching Sequences
match-case can be used with sequences such as lists and tuples to check their structure and access individual elements. It allows you to match sequences based on the number and arrangement of values they contain.
def process(data):
match data:
case [x, y]:
print(f"Two elements: {x}, {y}")
case [x, y, z]:
print(f"Three elements: {x}, {y}, {z}")
case _:
print("Unknown format")
process([1, 2])
process([1, 2, 3])
process([1, 2, 3, 4])
Output
Two elements: 1, 2 Three elements: 1, 2, 3 Unknown format
Explanation:
- [x, y] matches a sequence with exactly two elements.
- [x, y, z] matches a sequence with exactly three elements.
- Values are automatically assigned to the corresponding variables.
Matching Dictionaries
match-case can work with dictionaries by matching specific keys and their corresponding values. It can also extract values from matching keys and store them in variables for further use.
def person_info(data):
match data:
case {"name": name, "age": age}:
print(f"Name: {name}, Age: {age}")
case {"name": name}:
print(f"Name: {name}")
case _:
print("Unknown format")
person_info({"name": "Emily", "age": 25})
person_info({"name": "Harry"})
person_info({"city": "New York"})
Output
Name: Emily, Age: 25 Name: Harry Unknown format
Explanation:
- The first case matches dictionaries containing both "name" and "age".
- The second case matches dictionaries containing only "name".
- _ handles all other dictionary structures.
Matching Objects and Classes
match-case can be used with class instances to check an object's type and access its attributes. This makes it easier to handle different kinds of objects using separate matching patterns.
class Circle:
__match_args__ = ("radius",)
def __init__(self, radius):
self.radius = radius
class Rectangle:
__match_args__ = ("width", "height")
def __init__(self, width, height):
self.width = width
self.height = height
def check_shape(shape):
match shape:
case Circle(radius):
print(f"Circle radius: {radius}")
case Rectangle(width, height):
print(f"Rectangle: {width} × {height}")
case _:
print("Unknown shape")
check_shape(Circle(10))
check_shape(Rectangle(4, 6))
Output
Circle radius: 10 Rectangle: 4 × 6
Explanation:
- Circle(radius) matches a Circle object and extracts its radius.
- Rectangle(width, height) matches a Rectangle object and extracts both attributes.
- _ handles objects that do not match any specified pattern.
