如何继承 ABC 和另一个 class

How to inherit from ABC and another class

我有一个class

class A(ABC):
  @abstractmethod
  def m():
    pass

和一堆继承自它的 classes。

class M1(A):
  ...

class M2(A):
  ...

...

其中一些有很多共同点,因为它们共享很多功能,因此我想介绍一个公共基础 class,它本身继承自 A,但它不介绍任何新的 @abstractmethod 方法:


       A
       |
  +----+----+
  |    |    |
  M1   M2   B
            |
         +--+--+
         |     |
         K1   K2

class B 的定义应该是什么样的?

我在 Python 3.8

编辑: 我特意询问 PyCharm 告诉我“B 必须继承所有抽象方法”

您可以简单地使用

class B(A):
   pass

或所有儿童通用的任何其他代码,但没有 m。由于缺少 m.

,这仍然是抽象的

另一种方法是使用

class B(A, ABC):
   pass

在我看来这不太好。这说明 B 既是 A 又是 ABC,而前一个替代说明 BA,它是 [=16] =] 只要 A 本身就是 ABC

考虑一下您稍后决定 A 毕竟不是 ABC 的情况。对于 M1M2,无需进行任何更改。对于 B,您现在还需要将其删除为 ABC。虽然确保 AB 在子类化 ABC 中同步在代码维护方面并不是一个巨大的开销,但我认为这确实表明设计有问题,PyCharm 尽管有关于前一个替代方案的警告(我会将其抑制为误报)。

在您的特定情况下,您不需要混合任何东西。我个人不使用 Pycharm,但是创建 B 作为 A 的子类工作得很好并且 python 不会抱怨。

>>> from abc import ABC, abstractmethod
>>> class A(ABC):
...     @abstractmethod
...     def m(self):
...         pass
... 
>>> class B(A):
...     def common_method(self) -> str:
...         return 'b'
... 
>>> class K1(B):
...     def m(self) -> str:
...         return 'k1'
... 
>>> class K2(B):
...     def m(self) -> str:
...         return 'k2'
... 
>>> k1 = K1()
>>> k2 = K2()
>>> k1.m()
'k1'
>>> k2.m()
'k2'
>>> k1.common_method()
'b'
>>> k2.common_method()
'b'
>>> # However you can't do this
>>> b = B()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class B with abstract methods m

如果你有不同但相似的结构(不是直接问题但仍然相关)

       A        <----- this is not abstract
       |
  +----+----+
  |    |    |
  M1   M2   B   <------ you want this to be abstract and also group some
            |           functionality for K1 and K2
         +--+--+
         |     |
         K1   K2

您可以通过定义 metaclass 而不是将 ABCA 子类化为混合(元类无论如何都会完成所有工作),而无需混合 类 .以下是您的操作方法。

>>> from abc import ABCMeta, abstractmethod
>>> class A:
...     def m(self) -> str:
...         return 'a'
... 
>>> class B(A, metaclass=ABCMeta):
...     @abstractmethod
...     def n(self):
...         pass
...     def common_method(self) -> str:
...         return 'b'
... 
>>> class K1(B):
...     def n(self) -> str:
...         return 'k1'
... 
>>> class K2(B):
...     def n(self) -> str:
...         return 'k2'
... 
>>> k1 = K1()
>>> k2 = K2()
>>> k1.m()
'a'
>>> k2.m()
'a'
>>> k1.n()
'k1'
>>> k2.n()
'k2'
>>> k1.common_method()
'b'
>>> k2.common_method()
'b'
>>>