Аннотации типов для проверки isinstance - PullRequest
0 голосов
/ 18 июня 2020

У меня есть фрагмент кода, который выглядит примерно так:

T = TypeVar('T')

def filter_by_type(cls: Type[T]) -> Iterable[T]:
  for val in some_other_iterable():
    if isinstance(val, cls):
      yield val

Пока все хорошо. Но теперь я понял, что смогу передать не только один класс, но и кортеж классов. Сам нетипизированный код Python даже не требует для этого никаких изменений, поскольку isinstance действительно принимает кортеж в качестве второго аргумента. Но аннотации типов теперь стали очень сложными. По сути, я хочу следующее:

def filter_by_type(cls: Tuple[Type[T1], Type[T2], ...]]) -> Iterable[Union[T1, T2, ...]]:

В идеале я бы имел вышеуказанное в дополнение к исходной версии, и я считаю, что могу использовать для этого @ overload .

Я знаю, что возможно использовать Tuple[T, ...] для обозначения кортежа с неизвестным числом элементов, все типа T, но я не могу себе представить, чтобы это разумно распространялось на ситуацию, когда перечислено более одного явного элемента, как в моем случае.

Я сомневаюсь, что система pytype способна указать там все, что я хочу. Что ближе всего я могу найти? Лучшее, что у меня есть, - это перегрузки для фиксированного количества типов.

T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')

@overload
def filter_by_type(cls: Type[T1]) -> Iterable[T1]: ...
@overload
def filter_by_type(cls: Tuple[Type[T1]]) -> Iterable[T1]: ...
@overload
def filter_by_type(cls: Tuple[Type[T1], Type[T2]]) -> Iterable[Union[T1, T2]]: ...
@overload
def filter_by_type(cls: Tuple[Type[T1], Type[T2], Type[T3]]) -> Iterable[Union[T1, T2, T3]]: ...

def filter_by_type(cls):
  for val in some_other_iterable():
    if isinstance(val, cls):
      yield val
...