Подклассы NamedTuple дают несовместимый тип возвращаемого значения / тип аргумента - PullRequest
2 голосов
/ 20 февраля 2020

Рассмотрим следующий фрагмент кода:

class A_TUPLE(NamedTuple):
    ...

class Animal:
    def get(self) -> Sequence[NamedTuple]:
        ...

    def get_one(self, x: Sequence[NamedTuple]) -> None:
        ...

class Dog(Animal):
    def get(self) -> Sequence[A_TUPLE]:  # error: Return type "Sequence[A_TUPLE]" of "get" incompatible with return type "Sequence[NamedTuple]" in supertype "Animal"
        ...
    def get_one(self, x: Sequence[A_TUPLE]) -> None:  # error: Argument 1 of "get_one" is incompatible with supertype "Animal"; supertype defines the argument type as "Sequence[NamedTuple]"
        ...

Запуск mypy в приведенном выше фрагменте кода приводит к ошибке, как показано в комментариях.

Согласно mypy - invariance это должно быть возможно.

1 Ответ

1 голос
/ 21 февраля 2020

Sequence[NamedTuple] и Sequence[A_TUPLE] могут быть совместимы, только если имена / типы NamedTuple известны заранее. В противном случае, просто объявив NamedTuple, невозможно проверить, является ли возвращаемый тип производного класса совместимым или безопасным с базовым классом.

Например, это будет работать:

class A_TUPLE(NamedTuple):
    a: str
    b: int

class Animal:
    def get(self) -> Sequence[Tuple[str, int]]:
        ...

class Dog(Animal):
    def get(self) -> Sequence[A_TUPLE]:  # okay!
        ...

Вторая функция def get_one(self, x: Sequence[A_TUPLE]) имеет другую проблему. Версия базового класса говорит, что get_one () может принимать любой кортеж, тогда как производная версия требует определенного c типа A_TUPLE. Но если у вас есть собака, вы можете относиться к ней как к животному. Так что Собака должна принять все, что принимает Животное, а это не так.

...