我正在尝试创建一个简单的抽象基类Abstract
,它与自己的方法一起提供了另外两个抽象基类的方法:Publisher
和Subscriber
。当我尝试初始化基于Abstract
构建的具体类Concrete
时,我得到了以下错误:无法为基ABC、发布服务器、订阅服务器创建一致的方法解析顺序(MRO(。做这件事的正确方法是什么?
from abc import ABC, abstractmethod
class Publisher(ABC):
subscribers = set()
def register(self, obj):
self.subscribers.add(obj)
def unregister(self, obj):
self.subscribers.remove(obj)
def dispatch(self, event):
print("dispatching", event)
class Subscriber(ABC):
@abstractmethod
def handle_event(self, event):
raise NotImplementedError
class Abstract(ABC, Publisher, Subscriber):
@abstractmethod
def do_something(self, event):
raise NotImplementedError
class Concrete(Abstract):
def handle_event(self, event):
print("handle_event")
def do_something(self, event):
print("do_something")
c = Concrete()
抽象类的基列表中不必有abc.ABC
。它们必须有abc.ABCMeta
(或子类(作为元类,并且必须至少有一个抽象方法(或其他重要的方法,如抽象属性(,否则它们将被视为具体的。(Publisher
没有抽象的方法,所以它实际上是具体的。(
从ABC
继承只是将ABCMeta
作为类的元类的一种方式,对于比元类更熟悉继承的人来说,但这不是唯一的方式。您也可以从另一个以ABCMeta
为元类的类继承,或者显式指定metaclass=ABCMeta
。
在您的情况下,从Publisher
和Subscriber
继承已经将Abstract
的元类设置为ABCMeta
,因此从ABC
继承是多余的。从Abstract
的基类列表中删除ABC
,一切都会正常工作。
或者,如果您出于某种原因真的希望ABC
在其中,您可以将其移动到基类列表的末尾,这将解决MRO冲突-首先说您希望ABC
方法覆盖其他类的方法,这与其他类是ABC
的子类的事实相冲突。
从此更改:
class Abstract(ABC, Publisher, Subscriber):
对此:
class Abstract(Publisher, Subscriber):
这两个子类已经是抽象的,因此不需要再次从ABC
继承。
class摘要(发布者、订阅者、ABC(:
如果你想确保类不是可实例化的,这将是解决方案