What does an `as` pattern such as `case [x, y] as pair` bind in a `match`?
answer
- The keyword that keeps what you destructured
- Binds the value its left pattern matched
- Top level the subject, nested the part
- Pairs naturally with alternatives joined by a bar
basics
~20 sAn as pattern binds the name on its right to the value its left-hand pattern matched, on top of any names that pattern captured. At the top level that value is the whole subject; nested, it is only the sub-value.
solid answer
~50 s`pattern as NAME` is the AS pattern: if the left-hand pattern matches, `NAME` is bound to the value that pattern matched, on top of whatever the pattern itself captured. At the top level of a `case`, that value is the whole subject — `case [x, y] as pair:` gives you the elements *and* the list. In a sub-position it is that sub-value only: `case {"point": [_, _] as pair}:` binds `pair` to the inner list, not the mapping. It is the standard way to keep a value you have destructured or matched against alternatives, as in `case ("GET" | "HEAD") as verb:`. The binding happens before the case's guard runs, so the guard can read it. The target must be a real name — `case [1, 2] as _:` is a `SyntaxError: cannot use '_' as a target`.
code
python · 11 linesdef kind(token):
match token:
case ("GET" | "HEAD") as method:
return f"read:{method}"
case [first, *_] as whole:
return f"{first} of {whole}"
case _:
return "other"
print(kind("HEAD")) # read:HEAD
print(kind([1, 2, 3])) # 1 of [1, 2, 3]go deeper
Recognise pattern as name when you read a match statement and know it gives you a name for the thing that matched, on top of anything the pattern destructured. You will rarely be asked to write one.
Explain precisely which value is bound — the whole subject at the top level, the sub-value in a nested position — and show the common pairing with alternatives, case ("GET" | "HEAD") as method:.
Use it to keep cases readable instead of re-deriving the container in the body, and know the sharp edges: the wildcard cannot be a target, and an AS over an irrefutable pattern is itself irrefutable and makes later cases unreachable.
Treat it as a readability lever when setting match conventions: naming a matched value at the pattern rather than in the body keeps case bodies short, but a case carrying several as bindings usually wants to be a smaller, clearer set of cases.
## The problem it solves A pattern that destructures throws the container away. `case [x, y]:` gives you the two elements, but nothing that names the list itself. A literal or or-pattern is worse: `case "GET" | "HEAD":` tells you the subject was one of two strings but leaves you no name holding which one. The **AS pattern** fixes both. ## Syntax and semantics The form is `<pattern> as <name>`. The left-hand pattern is tried first. If it matches, `<name>` is bound to **the value that pattern matched**, in addition to any captures inside the pattern. If the left-hand pattern fails, nothing is bound by the AS pattern and the case is rejected as usual. The subtlety worth getting right in an interview is *which* value gets bound, and it depends on position: * **Top level of a `case`** — the value matched is the subject of the `match`, so `case [x, y] as pair:` binds `pair` to the whole sequence. * **A sub-position** — the value matched is only that sub-value. In `case {"point": [_, _] as pair}:` the name `pair` holds the inner two-element list; the mapping itself is not bound by anything. ```python def inspect(payload): match payload: case {"point": [_, _] as pair}: return pair case _: return None inspect({"point": [1, 2], "id": 7}) # [1, 2] ``` ## The idiomatic uses **Keeping the whole thing after destructuring.** When the body needs both the parts and the original — to re-emit it, log it, or pass it on — `as` saves a second lookup and keeps the case self-describing. **Naming the result of an or-pattern.** This is the pairing you will most often see: ```python match verb: case ("GET" | "HEAD") as method: return f"read: {method}" ``` Without `as`, the body knows the subject was one of the alternatives but has no name for which one. And because `as` binds the *same* name whichever alternative matched, it satisfies the or-pattern rule that every alternative bind the same names — with the bar inside the group and the `as` outside it, there is only one binding to reconcile. **Naming a value a pattern only tested.** A pattern that merely constrains the subject without destructuring it can be given a name in the same breath, keeping the case readable without a separate assignment in the body. ## Interaction with guards The `as` binding happens as part of matching, which completes before the case's guard is evaluated. So the guard may read it: `case ("GET" | "HEAD") as method if method in allowed:` works. As with every capture, the binding survives a failed guard — the name is still set even though the case was rejected — so restrict your use of it to the body of the case that bound it. ## Outside the alternatives or inside them Both placements compile, and they are worth being able to compare. `case ("a" | "b") as ch:` wraps the whole group and binds once, whichever alternative won. `case ("a" as ch) | ("b" as ch):` puts an `as` inside each alternative and is also legal — both alternatives bind exactly `{ch}`, so the rule that alternatives bind the same names is satisfied. The outer form is shorter, obviously correct by construction, and the one to reach for; the inner form only earns its keep when the alternatives need to bind *different* sub-values under the one shared name. ## Rules and errors The target must be a plain, valid name. The wildcard is not a name, so it cannot be a target: ```python case [1, 2] as _: # SyntaxError: cannot use '_' as a target ``` An AS pattern is **irrefutable exactly when its left-hand pattern is**. `case _ as everything:` matches anything, and just like a bare `case _:` it makes any following clause unreachable — the compiler reports `wildcard makes remaining patterns unreachable`. `case [x] as pair:` is refutable, because the sequence pattern can fail, so cases after it are fine. Note also that a bare capture name and an AS pattern are different constructs that happen to look related. `case pair:` is a capture pattern that matches everything and binds `pair`; `case [x, y] as pair:` still *tests* the subject and only then binds. Confusing the two is the mistake that produces an accidental catch-all. ## Where it sits AS patterns arrived with the rest of structural pattern matching in Python 3.10 (PEP 634) and have not changed through 3.14. They are a comfort feature rather than a gate — most interview `match` questions never reach them — but reaching for one naturally in a live-coding exercise reads as fluency with the statement.
- In `case {"point": [_, _] as pair}:`, is `pair` bound to the mapping or to the inner list?To the inner list. An AS pattern binds the value matched by the pattern immediately to its left, at the position where it appears. Here that pattern is the two-element sequence sub-pattern, so `pair` is the list. Only an `as` at the top level of the `case` binds the whole subject.
- How does `case value:` differ from `case [x, y] as value:`?`case value:` is a capture pattern: it matches absolutely anything and binds `value`, which makes it an irrefutable catch-all that must come last. `case [x, y] as value:` still tests that the subject is a two-element sequence and only binds on success, so it is refutable and later cases remain reachable.
- Can a case's `if` guard read a name bound by an `as` pattern?Yes. Matching, including every capture and every AS binding, completes before the guard is evaluated, so `case ("GET" | "HEAD") as method if method in allowed:` is valid and reads well. Like all captures, the binding persists even if the guard then rejects the case.
Unpacking a parcel to check its contents while keeping a label on the box itself, so you can still hand the whole parcel on afterwards.
saying these in an interview costs you the question
- Says a nested `as` binds the whole subject
- Thinks `as` only works on class patterns
- Believes `case x as _:` is valid syntax
- Confuses `as` with a bare capture catch-all pattern
- Claims the guard cannot see an `as` binding