mypy泛型子类导致不兼容的类型

时间:2017-10-28 15:41:51

标签: python generics inheritance mypy invariance

我正在使用类型提示实现幺半群。为此我写了:

M = TypeVar('M')

class Monoid(Generic[M]):
    ...
    def append(self, m: 'Monoid[M]') -> 'Monoid[M]':
        raise NotImplementedError()

在子类中使用它时,例如

A = TypeVar('A')

class List(Monoid[A], Generic[A]):
    def __init__(self, *values: A) -> None:
        self._values = tuple(values)
    ...
    def append(self, m: 'List[A]') -> 'List[A]':
        return List(*(self.values + m.values))

我得到error: Argument 1 of "append" incompatible with supertype "Monoid"。由于ListMonoid的正确子类,我希望能够输入。我做错了什么?

1 个答案:

答案 0 :(得分:1)

好吧,你的List不是一个正确的Monoid子类型。毕竟,你声明所有Monoids必须有一个append方法,可以接受Monoid的任意Monoid或子类 - 所以,为什么缩小List以使其append只能接受专门的List?

这违反了Liskov substitution principle

您可以使用generic self

解决此特定情况
M = TypeVar('M')
T = TypeVar('T')

class Monoid(Generic[M]):
    ...
    def append(self: T, m: T) -> T:
        raise NotImplementedError()

现在,您要表示Monoid的所有子类都必须实现一个append方法,该方法特别接受该子类类型。使用这个新版本的Monoid,您的List类现在是类型安全的。