In a Python match statement, what does `case [a, b, *rest]` match, and what does it bind?
answer
- Two tests run before anything binds
- Type first, then how many items
- At most one of them per pattern
- Brackets and parentheses mean the same
basics
~20 sIt matches any sequence of at least two items - a list, tuple, range, deque and so on, but never a str or bytes. The first two items bind to a and b, and everything left over binds to rest as a new list.
solid answer
~40 sA sequence pattern runs two tests. First a type test: the subject must be a sequence in the pattern-matching sense - `list`, `tuple`, `range`, `memoryview`, `array.array`, `collections.deque`, or a class inheriting from or registered with `collections.abc.Sequence`. `str`, `bytes` and `bytearray` are deliberately excluded. Then an arity test: with no star the pattern matches that exact length, so `case [a, b]` needs exactly two items and `case []` only an empty sequence. One star relaxes that to a minimum arity, and the star may sit anywhere, so `[first, *middle, last]` still needs at least two items. The starred name always binds a fresh `list`, even when the subject is a tuple, and `*_` matches the rest without binding it. Square brackets and parentheses mean exactly the same thing in a pattern.
code
python · 16 linesdef summarize(row):
match row:
case []:
return "no fields"
case [name]:
return f"only {name}"
case [name, count]:
return f"{name} = {count}"
case [name, count, *extra]:
return f"{name} = {count} (+{len(extra)} more)"
case _:
return "not a sequence"
print(summarize(["retries", 17, "a", "b"]))
print(summarize(("retries", 17)))
print(summarize("retries"))go deeper
Recall the two rules: no star means an exact length, one star means at least that many, and the starred name comes back as a list. Be able to read a small ladder of cases and say which subject hits which branch.
Explain the mechanics: the type test that excludes str and bytes, why brackets and parentheses are interchangeable, why case (n) is a capture rather than a one-item pattern, and that the starred slice is copied into a fresh list.
Show judgement about ordering the cases from specific to general, and about cost - a starred pattern materialises a list, so peeling a head off a large sequence in a hot loop is not free. Know when ordinary unpacking is the clearer tool.
Own the guidance for when shape-dispatch beats a chain of isinstance checks or a dict of handlers, and how far a codebase should push structural matching before the shapes deserve real types instead.
A sequence pattern is the bracketed or parenthesised form written on the left of a `case`. It is not a constructor and it never builds a container: it is a test plus a set of bindings, and it runs in three stages: 1. a type test, 2. an arity test, 3. then recursive matching of the sub-patterns against the elements. ## Stage one: the type test Pattern matching does not duck-type here. The interpreter checks a flag on the subject's type that is set for classes which inherit from or are registered with `collections.abc.Sequence`. - The built-in types that carry it are `list`, `tuple`, `range`, `memoryview`, `array.array` and `collections.deque`. - Three that you might expect are excluded on purpose: `str`, `bytes` and `bytearray`. - Also excluded, because they are not sequences at all, are `dict` and `set`, and every iterator or generator object - matching would have to consume the iterator to measure it, so a sequence pattern simply fails against one. - A hand-written class that defines only `__len__` and `__getitem__` fails the test too; opting in is an explicit act. ## Stage two: the arity test With no starred sub-pattern the length must match **exactly**. `case []` matches only an empty sequence; `case [x]` only a one-item one; `case [a, b]` only a two-item one. Add one star and the pattern becomes a **minimum-arity** test instead: - `[a, b, *rest]` matches two or more items, - `[*rest]` matches any sequence at all, - and the star does not have to be last - `[first, *middle, last]` matches two or more, binding the ends and collecting whatever lies between them. At most one star is allowed per sequence pattern; two raise a `SyntaxError` reading `multiple starred names in sequence pattern` when the module is compiled, not at match time. ## Stage three: the bindings Non-starred sub-patterns are matched against the corresponding elements, and a bare name there is a capture that always succeeds and binds. The starred name is different in one respect that trips people up: it **always binds a brand-new `list`**, whatever the subject's type was. Match `(1, 2, 3)` against `[x, *rest]` and `rest` is `[2, 3]`, a list, not a tuple. That copy is real work - the starred region is materialised, so the pattern costs O(k) in the size of the collected slice, which matters if you write `[first, *rest]` inside a loop over a large sequence just to peel off a head. ## Brackets, parentheses and the one-element trap There is no list-pattern versus tuple-pattern distinction: `case [a, b]` and `case (a, b)` are the same pattern and both match a list, a tuple or a range of length two. The one place the punctuation matters is a single name: - `case (n)` is just a parenthesised group around a capture pattern, so it matches anything at all and binds the whole subject; - `case (n,)` and `case [n]` are one-element sequence patterns. Reaching for the wrong one is the classic silent bug in this area, because the group form always succeeds and quietly swallows every later case. ## Nesting Sub-patterns are patterns, so shapes compose: `case [name, [x, y], *rest]` matches a sequence whose second element is itself a two-item sequence. This is what makes sequence patterns worth having over ordinary unpacking - unpacking a mis-shaped value raises `ValueError`, whereas a pattern that does not fit simply fails and control falls to the next `case`. ## How to order the cases Because the first matching case wins, write the ladder from most specific to least: 1. the empty sequence, 2. then the fixed arities you care about, 3. then the starred catch-all. Inverting that order makes the general pattern shadow the specific ones, and nothing warns you. A tidy dispatch reads as a small table of shapes - zero fields, one field, two fields, two-plus-extras - and each branch knows precisely how many names it has. One last framing that keeps the mental model straight: a sequence pattern asks *is this shaped like this, and if so give me the pieces*. It answers with a boolean and, on success, with bindings - never with a new container, and never by iterating the subject.
- Does `case (a, b)` match a list, or only a tuple?Both. Pattern syntax draws no list-versus-tuple distinction: `case (a, b)` and `case [a, b]` compile to the same test and match any two-item sequence, including a `list`, a `tuple` or a `range`. Choose whichever reads better; neither constrains the subject's concrete type. If you need that constraint, test the type explicitly rather than relying on the brackets.
- How many starred names may one sequence pattern contain?Exactly one at most. Two raise `SyntaxError: multiple starred names in sequence pattern` at compile time, because with two the split point would be ambiguous. The single star may appear anywhere in the pattern - first, last or in the middle - and everything not covered by the fixed sub-patterns is collected into it.
- What is the difference between `case (n)` and `case (n,)`?`case (n)` is a parenthesised group around a capture pattern: it matches any subject and binds the whole thing to `n`, so every later case is unreachable. `case (n,)` is a one-element sequence pattern, equivalent to `case [n]`, and matches only a sequence of length one. The trailing comma is load-bearing.
It is a shape template held up against the value: the outline has to be the right kind of thing and the right number of slots, and only then do the pieces drop into named holes.
saying these in an interview costs you the question
- Thinks `case [a, b]` matches any sequence starting with two items
- Believes square brackets match lists and parentheses match tuples
- Expects the starred name to keep the subject's type
- Says a generator or iterator matches a sequence pattern
- Writes two starred names in one pattern
- Treats `case (n)` as a one-element sequence pattern