Python’s Structural Pattern Matching: Advanced Branching and Data Extraction with match-case

“Structural Pattern Matching (match statement),” introduced in Python 3.10, is a powerful feature. It goes beyond simple value comparison; it branches based on the structure of data (lists, tuples, dictionaries, objects, etc.) and can simultaneously extract the contents into variables.

It is more readable than traditional if-elif-else statements and is especially effective when handling complex data structures. This article explains the comprehensive usage of the match statement, from basic value matching to object attribute matching.


目次

Basic Value Matching and Default Action

This checks if a variable’s value matches a specific literal (like a number or string). This usage is similar to the if statement or the switch statement in other languages. case _: is called a “wildcard” and defines the default action (equivalent to else) when no other pattern matches.

http_status = 404

match http_status:
    case 200:
        print("Request Successful")
    case 404:
        print("Page Not Found")
    case 500:
        print("Server Error")
    case _:
        # If none of the conditions apply
        print("Unknown Status Code")

Output:

Page Not Found

Matching Multiple Values (OR Patterns)

By using the pipe symbol |, you can describe a condition where the value matches any of multiple values (OR condition).

role = "editor"

match role:
    case "admin" | "manager":
        print("You have administrative privileges.")
    case "editor" | "viewer":
        print("You have viewing privileges.")
    case _:
        print("You do not have permissions.")

Output:

You have viewing privileges.

Conditional Checks (Guard)

By adding an if after the case statement, you can set a “Guard condition.” The block executes only if the pattern matches and the specific condition is met.

point = 85

match point:
    # Assign value to variable 'p' and check if 'p' is 90 or more
    case p if p >= 90:
        print(f"Score: {p} - Excellent")
    case p if p >= 70:
        print(f"Score: {p} - Passed")
    case _:
        print("Failed")

Output:

Score: 85 - Passed

Assigning to Variables (Capture)

If you specify a variable name in the case, the matched value is assigned to that variable. This allows you to use that value within the branch.

response_code = 418

match response_code:
    case 200:
        print("OK")
    # Capture the value into the variable 'code'
    case code:
        print(f"An error occurred. Code: {code}")

Output:

An error occurred. Code: 418

Sequence Unpacking (Tuples/Lists)

You can match sequence structures like lists or tuples and extract internal elements into individual variables.

# Coordinate data (x, y)
coordinate = (15, 20)

match coordinate:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"On Y-axis: y={y}")
    case (x, 0):
        print(f"On X-axis: x={x}")
    case (x, y):
        print(f"Coordinate: x={x}, y={y}")

Output:

Coordinate: x=15, y=20

Separating Head and Tail (Rest Pattern)

Using a variable with an asterisk * allows you to receive the remaining elements of a list as a list. This is useful for parsing command-line arguments.

command = ["move", 10, 20, 5]

match command:
    case ["quit"]:
        print("Exiting")
    # First element is "move", store the rest in 'params'
    case ["move", *params]:
        print(f"Move command: Params {params}")
    case _:
        print("Unknown command")

Output:

Move command: Params [10, 20, 5]

Dictionary Matching

You can match based on the structure of a dictionary. Dictionary matching checks if the specified keys exist (partial match). It is also possible to capture the values of specific keys.

user_info = {"id": 101, "role": "admin", "name": "tanaka"}

match user_info:
    # If "role" is "guest"
    case {"role": "guest"}:
        print("Guest User")
    
    # If "role" is "admin", capture "name" into variable 'n'
    case {"role": "admin", "name": n}:
        print(f"Logged in as Admin: {n}")
    
    case _:
        print("Standard User")

Output:

Logged in as Admin: tanaka

Object Attribute Matching

You can also match against class instances based on their type and attributes.

class Button:
    def __init__(self, label, color):
        self.label = label
        self.color = color

# Button instance
ui_element = Button("Submit", "blue")

match ui_element:
    # Button class where color is "red"
    case Button(color="red"):
        print("Danger Button")
    
    # Button class where color is "blue", capture label into 'l'
    case Button(label=l, color="blue"):
        print(f"Blue Button: {l}")
    
    case _:
        print("Other UI Element")

Output:

Blue Button: Submit

Summary

Python’s Structural Pattern Matching (match statement) allows you to write the following operations in a unified syntax:

  • Simple value comparison
  • Variable capture (assignment)
  • Detailed judgment using Guard conditions
  • Structural analysis and unpacking of lists and dictionaries
  • Determination of object classes and attributes

Use it proactively to write complex conditional branching concisely.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次