我有一个做某事的父类和两个以正交方式包装方法的子类。当我尝试将两个子类合并时,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
Mypy抱怨只是因为您试图从Foo和Bar继承C,它们运行的方法相同,但参数不同。要使Mypy满意,您必须使Foo和Bar类中的运行函数相同(匹配相同的函数签名),或者不要从它们两者继承C类。
一个简单的解决方法是设置foo
和bar
仅关键字参数:
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
的值。通常,即使在运行时3
绑定到第一个调用的方法的第一个可用参数上,将positional参数添加到重写方法的签名中也是一个坏主意。
而且,因为无法通过foo
的实例传递bar
和C
的位置参数,所以无论如何都必须将它们作为关键字参数传递,因此您也可以这样声明它们。