pythonlisttuplespattern-matchingpython-3.10

Why Python matches a list as a tuple?


With Python 3.11.0a2+, and the following code:

def my_fun(e):
    match e:
        case (1,):
            print("tuple (1,)")
        case [1]:
            print("list [1]")
        case _:
            print("I don't understand")

Calling the function with my_fun([1]) prints "tuple (1,)".

Is this behavior correct?

If I explicitly match against tuple((1, )) instead of (1,), it works as expected.

If this is not a bug of the interpreter, what is the reason behind this seemingly weird behavior?


Solution

  • This is documented under Structural Pattern Matching

    Like unpacking assignments, tuple and list patterns have exactly the same meaning and actually match arbitrary sequences. Technically, the subject must be a sequence. Therefore, an important exception is that patterns don’t match iterators. Also, to prevent a common mistake, sequence patterns don’t match strings.

    and in PEP 635 -- Structural Pattern Matching: Motivation and Rationale

    As in iterable unpacking, we do not distinguish between 'tuple' and 'list' notation. [a, b, c], (a, b, c) and a, b, c are all equivalent. While this means we have a redundant notation and checking specifically for lists or tuples requires more effort (e.g. case list([a, b, c])), we mimic iterable unpacking as much as possible.