比较两个类型注释(可能是泛型)看它们是否合适

Compare two type annotations (possibly generics) to see if they fit

我正在寻找一个函数,它可以判断一个类型注释是否是另一个类型注释的子集。

它可能在标准库或第 3 方中。由于 mypy 和 pytype 等类型检查器已经解决了这个问题,我假设有一些函数可以做到这一点,但找不到它。

例如函数 f 这样:

from typing import *

f(Sequence, List) # True
f(Sequence[str], List) # False
f(Iterable[str], List[str]) # True
f(List[str], Iterable[str]) # False
f(str, str) # True
f(int, str) # False

issubclass 适用于实际类型和简单类型注释,

issubclass(str, str) # True
issubclass(int, str) # False
issubclass(list, Sequence) # True
issubclass(Iterable, Sequence) # False
issubclass(Sequence, Iterable) # True

但不适用于仿制药:

issubclass(List[str], Iterable[str])

TypeError: Subscripted generics cannot be used with class and instance checks

高级目标是能够在给定两个函数的情况下确定它们是否可以组合。

最终我自己为常见用例实现了这个(OptionalUnionCallableTuple 和简单类型都可以)。

pip install gamla

那么用法是:

import gamla


def test_is_subtype():
    for x, y in [
        [FrozenSet[str], FrozenSet[str]],
        [str, Any],
        [Tuple[str, ...], Tuple[str, ...]],
        [Set[str], Collection[str]],
        [List, Sequence],
        [Union[int, str], Union[int, str]],
        [str, Union[int, str]],
        [Union[List, Set], Collection],
    ]:
        assert gamla.is_subtype(x, y)


def test_not_is_subtype():
    for x, y in [
        [FrozenSet[int], FrozenSet[str]],
        [str, FrozenSet[str]],
        [Collection, FrozenSet],
        [Tuple[str, ...], Tuple[int, ...]],
        [Union[int, str], int],
        [Any, str],
        [List, Union[int, str]],
        [Union[int, str, List], Union[int, str]],
    ]:
        assert not gamla.is_subtype(x, y)