简体   繁体   English

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

[英]mypy generic subclass leads to incompatible types

I'm toying around with implementing monoids with type hinting.我正在玩弄带有类型提示的幺半群。 To that end I've written:为此,我写道:

M = TypeVar('M')

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

When using this in a subclass, eg在子类中使用 this 时,例如

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))

I get error: Argument 1 of "append" incompatible with supertype "Monoid" .我收到error: Argument 1 of "append" incompatible with supertype "Monoid" Since List is a proper subclass of Monoid , I would expect this to be able to type.由于ListMonoid的适当子类,我希望它能够输入。 What am I doing wrong?我究竟做错了什么?

Well, your List class isn't a proper subtype of Monoid.好吧,您的List不是Monoid 的正确子类型。 After all, you stated that all Monoids must have an append method that can accept any arbitrary Monoid or subclass of Monoid -- so, why is it ok to narrow List so that its append can accept only specifically List?毕竟,您说过所有 Monoid 都必须有一个 append 方法,可以接受任意 Monoid 或 Monoid 的子类——那么,为什么可以缩小 List 的范围,使其append只能接受特定的 List?

It's a violation of the Liskov substitution principle .这违反了Liskov 替换原则

You can work around this specific case by using a generic self :您可以使用通用 self解决此特定情况:

M = TypeVar('M')
T = TypeVar('T')

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

Now, you're expressing that all subclasses of Monoid must implement an append method that accepts specifically whatever that subclass type is.现在,您表示Monoid所有子类都必须实现一个append方法,该方法专门接受该子类的类型。 With this new version of Monoid, your List class is now typesafe.有了这个新版本的 Monoid,你的 List 类现在是类型安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM