Mypy方法定义与基类中的定义不兼容

时间:2018-10-26 23:43:34

标签: python python-3.x mypy python-typing

我有一个做某事的父类和两个以正交方式包装方法的子类。当我尝试合并两个子类时,mypy会抱怨以下错误。

  

基类“ Foo”中“ run”的定义与   基类“ Bar”中的定义

两个类如何“不兼容”?如何修改代码以安抚mypy?我可以不做吗

class Parent:
    def run(self, a, b):
        pass


class Foo(Parent):
    def run(self, a, b, foo=None, **kwargs):
        print('foo', foo)
        super().run(a, b, **kwargs)


class Bar(Parent):
    def run(self, a, b, bar=None, **kwargs):
        print('bar', bar)
        super().run(a, b, **kwargs)


class C(Foo, Bar):
    pass

2 个答案:

答案 0 :(得分:1)

Mypy抱怨的原因仅在于您试图从Foo和Bar继承C,它们运行的​​方法相同,但参数不同。 为了使Mypy开心,您必须使Foo和Bar类中的运行函数相同(匹配相同的函数签名),或者不要从这两个类继承C类。

答案 1 :(得分:0)

一个简单的解决方法是制作foobar仅关键字的参数:

class Parent:
    def run(self, a, b):
        pass


class Foo(Parent):
    def run(self, a, b, *, foo=None, **kwargs):
        print('foo', foo)
        super().run(a, b,  **kwargs)


class Bar(Parent):
    def run(self, a, b, *, bar=None, **kwargs):
        print('bar', bar)
        super().run(a, b, **kwargs)


class C(Foo, Bar):
    pass

使用位置参数的问题在于,mypy不能告诉您是否要像C().run(1,2,3)那样进行呼叫,每个呼叫应如何处理3。将C视为Foo,它应该是foo的值。但是,将C视为Bar,它应该是bar的值。通常,将 positional 参数添加到重写方法的签名是一个坏主意,即使在运行时3将绑定到第一个方法中第一个可用的参数上。 / p>

此外,由于无法通过foo的实例传递barC的位置参数,因此无论如何您都必须将它们作为关键字参数传递,因此您可能并这样声明它们。