Structural Pattern Matching Overview

🏷️ Conditional Logic and Decision Making / The Match Statement

🧠 Context Introduction

Python 3.10 introduced a powerful new feature called Structural Pattern Matching. Think of it as a supercharged version of the traditional if-elif-else chain. Instead of just checking if a value equals something, pattern matching lets you inspect the structure of your dataβ€”checking types, shapes, and nested values all at once. For engineers dealing with configuration files, API responses, or command parsing, this feature makes code cleaner, more readable, and less error-prone.


βš™οΈ What is Structural Pattern Matching?

At its core, structural pattern matching allows you to match a value against a series of patterns. A pattern can be:

  • A simple literal value (like 42 or "error")
  • A variable name that captures the value
  • A type check (like int(x) or str(y))
  • A sequence pattern (like [a, b, c])
  • A mapping pattern (like {"key": value})
  • A combination of the above with guards (extra conditions)

The syntax uses the keywords match and case instead of if and elif.


πŸ› οΈ Basic Syntax Breakdown

Here is the general structure of a match statement:

  • match keyword followed by the expression you want to evaluate
  • One or more case blocks, each with a pattern to match against
  • An optional case _: as a wildcard (like a default/else clause)
  • Each case block can have an optional guard using if for extra conditions

A simple example without code blocks:

  • match status_code:
  • case 200: print("Success")
  • case 404: print("Not Found")
  • case 500: print("Server Error")
  • case _: print("Unknown Status")

This replaces a traditional if status_code == 200: ... elif status_code == 404: ... chain.


πŸ“Š Comparison: Traditional If-Else vs. Match Statement

Feature Traditional If-Else Match Statement
Readability Can get messy with many conditions Clean, visual alignment of cases
Type Checking Requires isinstance() calls Built-in type patterns
Sequence Matching Manual indexing and length checks Automatic destructuring
Nested Data Complex nested conditions Natural structure matching
Performance Linear evaluation Optimized by Python interpreter
Default Case Requires explicit else Built-in case _: wildcard

πŸ•΅οΈ Common Use Cases for Engineers

1. Parsing Command-Line Arguments

Instead of manually splitting and checking sys.argv:

  • match sys.argv:
  • case ["script.py"]: run_interactive()
  • case ["script.py", "--help"]: show_help()
  • case ["script.py", "--config", path]: load_config(path)
  • case _: print("Invalid arguments")

2. Handling API Response Structures

When dealing with JSON responses that can have different shapes:

  • match response:
  • case {"status": "ok", "data": data}: process_data(data)
  • case {"status": "error", "message": msg}: log_error(msg)
  • case {"status": "rate_limit", "retry_after": seconds}: wait_and_retry(seconds)
  • case _: raise ValueError("Unexpected response format")

3. Processing Configuration Files

When config values can be different types:

  • match config_value:
  • case int(x): return x
  • case str(x) if x.isdigit(): return int(x)
  • case str(x): return x
  • case list(items): return [process_item(i) for i in items]
  • case _: raise TypeError(f"Unsupported config type: {type(config_value)}")

🎯 Advanced Patterns Worth Knowing

Sequence Patterns let you match lists or tuples by their structure:

  • case [a, b, c]: matches exactly three elements
  • case [first, *rest]: captures first element and remaining as a list
  • case [*all]: captures the entire sequence

Mapping Patterns work with dictionaries:

  • case {"name": name, "age": age}: matches dicts with those exact keys
  • case {"name": name, rest}:** captures name and remaining key-value pairs

Class Patterns let you match against custom objects:

  • case Point(x=0, y=0): matches a Point object at origin
  • case HTTPError(status=code): captures the status code from an error object

Guards add extra conditions to a pattern:

  • case int(x) if x > 0: matches only positive integers
  • case str(s) if len(s) > 10: matches strings longer than 10 characters

⚠️ Important Notes and Gotchas

  • Patterns are evaluated in order from top to bottom, just like if-elif
  • The first matching case wins, so put more specific patterns first
  • Variable names in patterns capture values, they don't compare against existing variables
  • Use literal patterns (like 42 or "hello") for exact matches
  • The wildcard _ is specialβ€”it never binds to a variable name
  • Pattern matching works with any Python data type, not just built-ins

🎬 When to Use (and When Not to Use)

Use pattern matching when:

  • You have multiple conditions checking the same variable
  • You need to destructure complex nested data
  • Your code involves type checking combined with value checking
  • You're parsing structured input (commands, configs, API responses)

Avoid pattern matching when:

  • You only have one or two simple conditions (use if-else)
  • You need to check unrelated variables (use separate if statements)
  • You're working with very large datasets (performance is comparable, but readability matters less)
  • Your team is on Python 3.9 or earlier (pattern matching requires Python 3.10+)

πŸ’‘ Quick Tips for Beginners

  • Start with simple literal matches before trying complex patterns
  • Use the wildcard case _: as your last case to catch unexpected values
  • Remember that patterns are about structure, not just values
  • Practice by converting existing if-elif chains to match statements
  • Use guards (if conditions) sparinglyβ€”if you need many guards, consider if the pattern is right for your use case

Structural pattern matching is one of Python's most elegant features for writing clear, expressive code. Once you get comfortable with the basics, you'll find yourself reaching for it naturally whenever you need to make decisions based on the shape and content of your data.


Structural pattern matching lets you compare a value against multiple patterns and execute code based on which pattern matches.

🎯 Example 1: Matching a single value

This example shows how to match a variable against a specific literal value.

status = 200

match status:
    case 200:
        result = "OK"
    case 404:
        result = "Not Found"

print(result)

πŸ“€ Output: OK


πŸ”€ Example 2: Matching multiple values with OR pattern

This example demonstrates matching one value against several possible matches using the pipe operator.

error_code = 403

match error_code:
    case 401 | 403:
        message = "Access denied"
    case 500:
        message = "Server error"

print(message)

πŸ“€ Output: Access denied


🧩 Example 3: Matching with a wildcard pattern

This example shows how to use an underscore as a catch-all for any unmatched value.

response_code = 302

match response_code:
    case 200:
        label = "Success"
    case 404:
        label = "Not Found"
    case _:
        label = "Other"

print(label)

πŸ“€ Output: Other


πŸ“¦ Example 4: Matching sequences (lists)

This example demonstrates matching a list against a pattern with specific elements and a variable for the rest.

command = ["move", "north", 5]

match command:
    case ["move", direction, distance]:
        action = f"Moving {direction} by {distance} units"
    case ["stop"]:
        action = "Stopping"
    case _:
        action = "Unknown command"

print(action)

πŸ“€ Output: Moving north by 5 units


πŸ› οΈ Example 5: Matching with guards (conditions)

This example shows how to add an if condition to a pattern for more specific matching.

point = (3, 4)

match point:
    case (x, y) if x == y:
        location = "On diagonal"
    case (x, y) if x > 0 and y > 0:
        location = "First quadrant"
    case _:
        location = "Other location"

print(location)

πŸ“€ Output: First quadrant


πŸ“Š Comparison: If-elif-else vs Match Statement

Feature If-elif-else Match Statement
Syntax Uses if, elif, else keywords Uses match, case keywords
Pattern types Only boolean expressions Supports literals, sequences, guards, wildcards
Readability Good for simple conditions Better for multiple distinct patterns
Performance Evaluates each condition in order Optimized for pattern matching
Use case Any logical condition Best when checking a single value against many patterns

🧠 Context Introduction

Python 3.10 introduced a powerful new feature called Structural Pattern Matching. Think of it as a supercharged version of the traditional if-elif-else chain. Instead of just checking if a value equals something, pattern matching lets you inspect the structure of your dataβ€”checking types, shapes, and nested values all at once. For engineers dealing with configuration files, API responses, or command parsing, this feature makes code cleaner, more readable, and less error-prone.


βš™οΈ What is Structural Pattern Matching?

At its core, structural pattern matching allows you to match a value against a series of patterns. A pattern can be:

  • A simple literal value (like 42 or "error")
  • A variable name that captures the value
  • A type check (like int(x) or str(y))
  • A sequence pattern (like [a, b, c])
  • A mapping pattern (like {"key": value})
  • A combination of the above with guards (extra conditions)

The syntax uses the keywords match and case instead of if and elif.


πŸ› οΈ Basic Syntax Breakdown

Here is the general structure of a match statement:

  • match keyword followed by the expression you want to evaluate
  • One or more case blocks, each with a pattern to match against
  • An optional case _: as a wildcard (like a default/else clause)
  • Each case block can have an optional guard using if for extra conditions

A simple example without code blocks:

  • match status_code:
  • case 200: print("Success")
  • case 404: print("Not Found")
  • case 500: print("Server Error")
  • case _: print("Unknown Status")

This replaces a traditional if status_code == 200: ... elif status_code == 404: ... chain.


πŸ“Š Comparison: Traditional If-Else vs. Match Statement

Feature Traditional If-Else Match Statement
Readability Can get messy with many conditions Clean, visual alignment of cases
Type Checking Requires isinstance() calls Built-in type patterns
Sequence Matching Manual indexing and length checks Automatic destructuring
Nested Data Complex nested conditions Natural structure matching
Performance Linear evaluation Optimized by Python interpreter
Default Case Requires explicit else Built-in case _: wildcard

πŸ•΅οΈ Common Use Cases for Engineers

1. Parsing Command-Line Arguments

Instead of manually splitting and checking sys.argv:

  • match sys.argv:
  • case ["script.py"]: run_interactive()
  • case ["script.py", "--help"]: show_help()
  • case ["script.py", "--config", path]: load_config(path)
  • case _: print("Invalid arguments")

2. Handling API Response Structures

When dealing with JSON responses that can have different shapes:

  • match response:
  • case {"status": "ok", "data": data}: process_data(data)
  • case {"status": "error", "message": msg}: log_error(msg)
  • case {"status": "rate_limit", "retry_after": seconds}: wait_and_retry(seconds)
  • case _: raise ValueError("Unexpected response format")

3. Processing Configuration Files

When config values can be different types:

  • match config_value:
  • case int(x): return x
  • case str(x) if x.isdigit(): return int(x)
  • case str(x): return x
  • case list(items): return [process_item(i) for i in items]
  • case _: raise TypeError(f"Unsupported config type: {type(config_value)}")

🎯 Advanced Patterns Worth Knowing

Sequence Patterns let you match lists or tuples by their structure:

  • case [a, b, c]: matches exactly three elements
  • case [first, *rest]: captures first element and remaining as a list
  • case [*all]: captures the entire sequence

Mapping Patterns work with dictionaries:

  • case {"name": name, "age": age}: matches dicts with those exact keys
  • case {"name": name, rest}:** captures name and remaining key-value pairs

Class Patterns let you match against custom objects:

  • case Point(x=0, y=0): matches a Point object at origin
  • case HTTPError(status=code): captures the status code from an error object

Guards add extra conditions to a pattern:

  • case int(x) if x > 0: matches only positive integers
  • case str(s) if len(s) > 10: matches strings longer than 10 characters

⚠️ Important Notes and Gotchas

  • Patterns are evaluated in order from top to bottom, just like if-elif
  • The first matching case wins, so put more specific patterns first
  • Variable names in patterns capture values, they don't compare against existing variables
  • Use literal patterns (like 42 or "hello") for exact matches
  • The wildcard _ is specialβ€”it never binds to a variable name
  • Pattern matching works with any Python data type, not just built-ins

🎬 When to Use (and When Not to Use)

Use pattern matching when:

  • You have multiple conditions checking the same variable
  • You need to destructure complex nested data
  • Your code involves type checking combined with value checking
  • You're parsing structured input (commands, configs, API responses)

Avoid pattern matching when:

  • You only have one or two simple conditions (use if-else)
  • You need to check unrelated variables (use separate if statements)
  • You're working with very large datasets (performance is comparable, but readability matters less)
  • Your team is on Python 3.9 or earlier (pattern matching requires Python 3.10+)

πŸ’‘ Quick Tips for Beginners

  • Start with simple literal matches before trying complex patterns
  • Use the wildcard case _: as your last case to catch unexpected values
  • Remember that patterns are about structure, not just values
  • Practice by converting existing if-elif chains to match statements
  • Use guards (if conditions) sparinglyβ€”if you need many guards, consider if the pattern is right for your use case

Structural pattern matching is one of Python's most elegant features for writing clear, expressive code. Once you get comfortable with the basics, you'll find yourself reaching for it naturally whenever you need to make decisions based on the shape and content of your data.

Interactive Views

You are currently in πŸ“š All-in-One mode. Use the tabs at the top to switch to πŸ“– Theory Only or πŸ’» Code Only views.

Structural pattern matching lets you compare a value against multiple patterns and execute code based on which pattern matches.

🎯 Example 1: Matching a single value

This example shows how to match a variable against a specific literal value.

status = 200

match status:
    case 200:
        result = "OK"
    case 404:
        result = "Not Found"

print(result)

πŸ“€ Output: OK


πŸ”€ Example 2: Matching multiple values with OR pattern

This example demonstrates matching one value against several possible matches using the pipe operator.

error_code = 403

match error_code:
    case 401 | 403:
        message = "Access denied"
    case 500:
        message = "Server error"

print(message)

πŸ“€ Output: Access denied


🧩 Example 3: Matching with a wildcard pattern

This example shows how to use an underscore as a catch-all for any unmatched value.

response_code = 302

match response_code:
    case 200:
        label = "Success"
    case 404:
        label = "Not Found"
    case _:
        label = "Other"

print(label)

πŸ“€ Output: Other


πŸ“¦ Example 4: Matching sequences (lists)

This example demonstrates matching a list against a pattern with specific elements and a variable for the rest.

command = ["move", "north", 5]

match command:
    case ["move", direction, distance]:
        action = f"Moving {direction} by {distance} units"
    case ["stop"]:
        action = "Stopping"
    case _:
        action = "Unknown command"

print(action)

πŸ“€ Output: Moving north by 5 units


πŸ› οΈ Example 5: Matching with guards (conditions)

This example shows how to add an if condition to a pattern for more specific matching.

point = (3, 4)

match point:
    case (x, y) if x == y:
        location = "On diagonal"
    case (x, y) if x > 0 and y > 0:
        location = "First quadrant"
    case _:
        location = "Other location"

print(location)

πŸ“€ Output: First quadrant


πŸ“Š Comparison: If-elif-else vs Match Statement

Feature If-elif-else Match Statement
Syntax Uses if, elif, else keywords Uses match, case keywords
Pattern types Only boolean expressions Supports literals, sequences, guards, wildcards
Readability Good for simple conditions Better for multiple distinct patterns
Performance Evaluates each condition in order Optimized for pattern matching
Use case Any logical condition Best when checking a single value against many patterns