Search code examples
typespattern-matchingpython-3.10

How to do structural pattern matching in Python 3.10 with a type to match?


I am trying to match a type in Python 3.10 using the console:

t = 12.0
match type(t):
  case int:
    print("int")
  case float:
    print("float")

And I get this error:

  File "<stdin>", line 2
SyntaxError: name capture 'int' makes remaining patterns unreachable

How can I fix this issue?


Solution

  • First, let's explain the code in the question:

    t = 12.0
    match type(t):
      case int:
        print("int")
      case float:
        print("float")
    

    In Python, the match statement operates by trying to fit the subject (the value of type(t), i.e. float) into one of the patterns.

    The above code has two patterns (case int: and case float:). These patterns, by nature of their syntax, are capture patterns, meaning that they attempt to capture the subject (the value of type(t), i.e. float) into the variable name specified in each pattern (the names int and float, respectively).

    The patterns case int: and case float: are identical to each other. Moreover, they will both match any subject. Hence, the error: SyntaxError: name capture 'int' makes remaining patterns unreachable.

    Additionally, note that these two patterns are functionally identical to the conventional default pattern of case _:. case _: is also simply a capture pattern, nothing more. (The only difference between case int:, case float: and case _: is the name of the variable that will capture the subject.)

    Now let's explain the code in @mmohaveri's answer.

    t = 12.0
    match t:
      case int():
        print("int")
      case float():
        print("float")
    

    The above match statement will attempt to fit the value 12.0 first into the pattern case int():, and then into the pattern case float():.

    These patterns, by nature of their syntax, are class patterns. The parentheses can be used to specify positional arguments and keyword arguments for the pattern. (The parentheses are not function calls.)

    For the first pattern (case int():), 12.0 is not an instance of int, so the pattern match fails.

    For the second pattern, (case float():), 12.0 is an instance of float, and no positional or keyword arguments are specified inside the parentheses, so the pattern match succeeds.

    Here is more information about the matching process.