NamedTuple的子类化提供了不兼容的返回类型/参数类型



考虑以下代码片段:

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不变性,这应该是可能的。

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((可以接受任何元组,而派生版本则需要特定的类型A_tuple。但如果你有一只狗,你可以把它当作动物。所以狗必须接受动物所接受的一切,但这里的情况并非如此。

最新更新