Traditionally, Python handled multi-way branching with if-elif-else chains or dictionary mappings. Python 3.10 introduced structural pattern matching, providing a declarative syntax to match complex data structures against specific patterns.
This article teaches you how to use the Python switch statement.

Does Python Have Switch Statement Functionality?
Python introduced match-case, a modern switch statement implementation, in version 3.10 through PEP 634 technical specification. While it functions similarly to switch statements in C++, Java, or JavaScript, the Python match-case statement offers more flexibility.
Standard switch statements typically compare a single value against several constants. Python’s implementation performs structural pattern matching, meaning it can inspect an object's type, shape, and internal attributes simultaneously.
Python match-case Syntax
The basic match-case block consists of a subject followed by one or more case patterns.
match [subject]:
case [pattern_1]:
[action_1]
case [pattern_2]:
[action_2]
case _:
[default_case]
The match keyword takes the expression for evaluation. Each case keyword precedes a comparison pattern. The underscore (_) acts as a wildcard, catching any input that fails to match previous patterns.
Python executes only the first matching block and then exits the match statement. This behavior eliminates the need for break statements common in other languages.
Python match-case Examples
Python match-case syntax supports everything from simple equality checks to complex data extraction. The following sections demonstrate how to apply these patterns in real-world programming scenarios.
Simple Value Matching
This example demonstrates a basic replacement for an if-elif chain. The logic compares the subject against literal values, such as integers or strings, to find an exact match:
def check_status(code):
match code:
case 200:
return "Success"
case 404:
return "Not Found"
case 500:
return "Server Error"
case _:
return "Unknown Status"
Matching Multiple Values
A single case can handle multiple inputs using the pipe (|) operator, which functions as a logical OR. Grouping reduces redundancy by allowing different patterns to trigger the same code block:
def get_day_type(day):
match day:
case "Saturday" | "Sunday":
return "Weekend"
case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday":
return "Weekday"
case _:
return "Unknown Day"

Matching with Conditions (Guards)
Guards add an if condition to a case pattern. The case matches only if the pattern fits and the condition evaluates to TRUE:
def categorize_age(age):
match age:
case n if n < 13:
return "Child"
case n if n < 20:
return "Teenager"
case n if n >= 20:
return "Adult"

Structural Matching (Lists and Tuples)
The match-case The statement unpacks sequences by checking both the length and the contents of a list or a tuple. This approach allows the program to capture specific elements into variables while verifying the overall structure of the data.
For instance, a command-line interface often receives input as a list of strings. The match statement can verify the command name and extract its arguments in a single step:
def process_command(command):
match command.split():
case ["quit"]:
exit()
case ["load", filename]:
print(f"Loading {filename}")
case ["move", x, y]:
print(f"Moving to {x}, {y}")
case _:
print("Command not recognized")
Python match-case Common Pitfalls
New users often assume match-case behaves exactly like a C-style switch or a standard if statement. Not recognizing how Python binds variables or orders execution can produce silent logic errors and broken code.
The following are some common mistakes made when working with switch statements in Python:
- Variable shadows. In a case pattern like
case status:, Python does not compare the subject to a variable named status. Instead, it binds the value of the subject to a new local variable status. To match against a constant, use a dotted name (e.g.,Constants.STATUS) or an enum. - Version compatibility. Code using
match-casefails on Python versions earlier than 3.10. This creates issues for legacy environments. - Order of operations. Python evaluates cases from top to bottom. Placing a wildcard (
_) or a broad variable capture at the top renders subsequent cases unreachable. - Overuse. Using
match-casefor simple boolean checks adds unnecessary complexity. Standardifstatements remain more readable for binary logic.
Python match-case Best Practices
Effective use of match-case relies on choosing the right data types and maintaining a logical flow from specific to general scenarios:
- Use enums. Enums prevent name binding issues and improve code clarity.
- Leverage the wildcard. A
case _:block should always be present, unless the logic explicitly requires an error for unhandled cases. This ensures the program remains predictable. - Avoid excessively nested patterns within a single case. If a pattern becomes hard to read, break it into smaller functions.
- Prioritize specificity. Place specific patterns at the top and general patterns at the bottom.
- Use guards sparingly. Use guards for logic that the pattern syntax cannot express. Over-reliance on guards turns the
matchstatement back into anif-elifchain.
Python match-case Alternatives
Before the introduction of match-case, Python used several functional and object-oriented patterns to handle branching. These alternatives remain useful for older environments or specific use cases where a full pattern match is unnecessary.
if-elif-else
The if-elif-else construct represents the standard way to handle conditional logic in Python. It evaluates expressions sequentially, checking each condition. If a condition is TRUE, Python executes the block and skips the rest.
if-elif-else handles ranges and complex Boolean logic more naturally than match-case. However, it lacks the structural unpacking capabilities of match-case, making it more verbose when extracting data from objects or lists.
Dictionary Mapping
Dictionaries map keys to values or functions, simulating a switch statement. To use dictionary mapping as a match-case alternative:
1. Create a dictionary where keys represent the cases and values represent the results or callable functions.
2. Use the .get() method to provide a default value.
Dictionary lookups offer O(1) average time complexity (highest level of efficiency), making them useful for many constant values. However, unlike match-case, dictionaries cannot handle patterns, ranges, or conditional guards without significant boilerplate.
getattr for Dispatching
The getattr function permits dynamic method dispatch based on a string. A class defines methods for different cases. getattr(instance, method_name) retrieves the method for execution.
This method organizes logic into distinct functions, which helps with large-scale systems. It feels more object-oriented than match-case, but it relies on string manipulation, which increases the risk of runtime errors.
Handling Logic with Polymorphism
Subclasses can override a base class method to provide specific behavior. Instead of checking a type inside a match block, the program calls a method on an object. The object's class determines which implementation runs.
Polymorphism removes the need for explicit switch-like logic. While cleaner for architectural design, it requires more setup code than a simple match-case block.
Conclusion
This article showed you how to use match-case as a switch statement in Python. It provided examples, best practices, and common problems with the match-case syntax, alongside alternatives.
Next, read our comprehensive overview of Python data types.



