python 使用默认参数输入抽象方法

Gav*_*llo 5 python python-3.x mypy

我有点困惑我应该如何输入基类抽象方法?

在这种情况下,我的基类只要求继承类实现一个名为“learn”的方法,该方法返回 None 而不强制任何参数。

class MyBaseClass(ABC):
    @abstractmethod
    def learn(self, *args, **kwargs) -> None:
       raise NotImplementedError()
Run Code Online (Sandbox Code Playgroud)

但如果我实现它 mypy 会引发错误““学习”签名与超类型“MyBaseClass”不兼容”

class MyOtherClass(MyBaseClass):
    def learn(self, alpha=0.0, beta=1) -> None:
       # do something
       return None
Run Code Online (Sandbox Code Playgroud)

那么我应该如何在基类中声明 learn 方法呢?

Joe*_*ley 2

首先,我想问为什么你想要一个没有已知参数的方法。这听起来像是一个设计问题。

一种解决方案

如果这些参数具有默认值(并且基类不使用**kwargs),则可以向子类添加新参数,例如

class MyBaseClass:
    @abstractmethod
    def learn(self) -> None:
       raise NotImplementedError()

class MyOtherClass(MyBaseClass):
    def learn(self, alpha=0.0, beta=1) -> None:
       ...
Run Code Online (Sandbox Code Playgroud)

尽管您无法指定alpha,并且beta如果您只知道它是MyBaseClass

def foo(x: MyOtherClass) -> None:
    x.learn(alpha=3)  # ok

def foo(x: MyBaseClass) -> None:
    x.learn(alpha=3)  # not ok
Run Code Online (Sandbox Code Playgroud)

为什么不起作用*args, **kwargs

如果你有

class MyBaseClass(ABC):
    @abstractmethod
    def learn(self, *args, **kwargs) -> None:
       raise NotImplementedError()
Run Code Online (Sandbox Code Playgroud)

然后考虑函数

def foo(x: MyBaseClass) -> None:
    ...
Run Code Online (Sandbox Code Playgroud)

在该函数中,您可以将任何内容传递给x.learn,例如x.learn(1, fish='three')。对于任何 . 都必须如此x。由于x可以是 的子类的实例MyBaseClass(例如MyOtherClass),因此该子类也必须能够接受这些参数。