Python Match Case Wildcard: Using _ and as Patterns
python match case wildcard: Learn how to use wildcard patterns in Python's match statement, including the underscore wildcard, capturing wildcards with as, and orderin...
The wildcard pattern in Python's match statement is written as _ and matches any value without binding it to a name. This article explains how python match case wildcard works, including capturing wildcards, ordering, and practical usage in real code.
The Basic Wildcard Pattern
The simplest wildcard is the single underscore _. In a match statement, it matches any value and does not bind it to a variable. This is useful when you need a default case or when you want to ignore a specific part of a structure.
command = input() match command.split(): case ["quit"]: print("Goodbye") case ["hello", name]: print(f"Hello, {name}") case _: print("Unknown command")
Here, case _ catches any list that doesn't match the previous patterns. The underscore is not a variable; it simply means "match anything". You cannot use _ as a variable name in the case block because it is reserved for wildcard behavior.
Capturing Wildcards with as
Sometimes you need to match any value but also keep a reference to it. The as keyword allows you to bind the matched value to a name. This is often called a capturing wildcard.
match value: case int() as number: print(f"Integer: {number}") case str() as text: print(f"String: {text}") case other: print(f"Something else: {other}")
The final case other is a wildcard that captures the entire value into other. This is equivalent to case _ as other but the underscore is implicit when you provide a name. Note that case other is a capture pattern, not a wildcard in the strict sense, but it behaves like one when used as the last case.
Ordering Matters: Wildcards as Default Cases
A wildcard pattern will match any value, so it must be placed last if you want earlier patterns to have a chance. Python evaluates cases in order and uses the first match. If you put a wildcard first, it will always match and later cases become unreachable.
match status: case _: print("Default") case 200: print("OK")
This code will always print "Default" because _ matches everything. The case 200 is never evaluated. To avoid this, put the wildcard last. This is not a performance issue but a correctness one. The interpreter does not optimize for unreachable patterns; it simply follows the order you write.
Wildcards in Sequence and Mapping Patterns
Wildcards can appear inside sequence and mapping patterns to ignore parts of a structure. For example, to match a list where the first element is "config" and ignore the rest:
match data: case ["config", *_]: print("Configuration found") case ["data", first, *_]: print(f"First data item: {first}")
The *_ pattern matches zero or more elements and does not bind them. Similarly, in mapping patterns, you can use **_ to ignore extra keys:
match request: case {"method": "GET", **_}: print("GET request") case {"method": "POST", "body": body, **_}: print(f"POST body: {body}")
Here, **_ matches any remaining keys without binding them. This is useful when you only care about specific fields and want to ignore the rest.
Combining Wildcards with Guards
A guard is an if condition attached to a case. You can use a wildcard pattern with a guard to create a conditional default. This is useful when you want to match any value but only under certain conditions.
match value: case _ if value is None: print("No value") case _ if value == "": print("Empty string") case _: print("Something else")
In this example, the first two cases use a wildcard with a guard. They match any value but the guard restricts when they apply. The final case _ is the unconditional default. Guards are evaluated only after the pattern matches, so a wildcard with a guard is a precise way to filter values without binding them.
Performance and Maintainability Considerations
Pattern matching is implemented efficiently in CPython, and the wildcard pattern adds no measurable runtime overhead compared to a simple if-elif-else chain. The main cost is the order of evaluation: each case is tested sequentially until a match is found. For a small number of cases, this is negligible. For long chains, consider grouping patterns or using dictionaries for dispatch.
From a maintainability perspective, wildcards improve readability when you have many distinct cases. They also make it clear that a default behavior exists. However, overusing wildcards can hide bugs if you accidentally match unexpected values. Prefer explicit patterns for known cases and reserve wildcards for genuinely unknown input.
Compatibility is a key constraint: the match statement was introduced in Python 3.10. If your code must run on older versions, you cannot use it. For projects that require Python 3.9 or earlier, stick to if-elif-else chains. When you do adopt pattern matching, use wildcards judiciously to keep the logic transparent.
When to Prefer Wildcards Over if-elif-else
Wildcards in match are not always the best choice. They shine when you are destructuring complex nested data, such as parsing command-line arguments or processing JSON payloads. In those cases, a wildcard inside a sequence or mapping pattern avoids verbose manual indexing and type checks. For simple scalar comparisons, an if-elif-else chain is often clearer and more familiar to other developers.
Consider the tradeoff: pattern matching gives you concise destructuring and guards, but it introduces a new syntax that some team members may not know. If your team is comfortable with Python 3.10+, the wildcard pattern is a powerful tool. If not, stick to traditional branching. The decision should be based on the structure of your data and the team's familiarity with the feature.