mypy 通用子类导致不兼容的类型

mypy generic subclass leads to incompatible types

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

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 的适当子类,我希望它能够键入。我做错了什么?

好吧,你的 List class 不是 Monoid 的正确子类型。毕竟,您声明所有 Monoid 都必须有一个 append 方法,该方法可以接受任意 Monoid 或 Monoid 的 subclass —— 那么,为什么可以缩小 List 使其 append 只能接受具体列表?

这违反了 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 的所有子class 必须实现一个 append 方法,该方法专门接受任何子class 类型。使用这个新版本的 Monoid,您的列表 class 现在是类型安全的。