Pattern matching to check a protocol. Getting TypeError: called match pattern must be a type
Asked Answered
I

1

5

I need to match cases where the input is iterable. Here's what I tried:

from typing import Iterable

def detector(x: Iterable | int | float | None) -> bool:
    match x:
        case Iterable():
            print('Iterable')
            return True
        case _:
            print('Non iterable')
            return False

That is producing this error:

TypeError: called match pattern must be a type

Is it possible to detect iterability with match/case?

Note, these two questions address the same error message but neither question is about how to detect iterability:

Involucrum answered 1/3, 2022 at 19:41 Comment(0)
I
8

The problem is the typing.Iterable is only for type hints and is not considered a "type" by structural pattern matching. Instead, you need to use an abstract base class for detecting iterability: collections.abc.Iterable.

The solution is distinguish the two cases, marking one as being a type hint and the other as a class pattern for structural pattern matching:

def detector(x: typing.Iterable | int | float | None) -> bool:
    match x:
        case collections.abc.Iterable():
            print('Iterable')
            return True
        case _:
            print('Non iterable')
            return False

Also note that at the time of this writing mypy does not support the match statement.

Involucrum answered 1/3, 2022 at 19:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.