Python: 如何创建继承他人ABC的ABC?

Python: How to create an ABC that inherits from others ABC?

我正在尝试创建一个简单的抽象基础 class Abstract,它连同它自己的方法提供了另外两个抽象基础 classes 的方法:PublisherSubscriber。当我尝试初始化基于 Abstract 的具体 class Concrete 时,出现此错误:无法创建一致的方法解析顺序 (MRO)对于基础 ABC、发布者、订阅者。正确的做法是什么?

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()

由此变化:

class Abstract(ABC, Publisher, Subscriber):

为此:

class Abstract(Publisher, Subscriber):

这两个子类已经是抽象类了,不需要再继承ABC

摘要 classes 不必在其碱基列表中包含 abc.ABC。他们必须有 abc.ABCMeta (或后代)作为他们的元 class,并且他们必须至少有一个抽象方法(或其他重要的东西,如抽象 属性),否则它们将被视为具体的。 (Publisher没有抽象方法,所以它实际上是具体的。)

ABC 继承只是将 ABCMeta 作为 class 的元 class 的一种方式,对于比元 [=38 更习惯继承的人来说=]es,但这不是唯一的方法。您还可以从另一个 class 继承 ABCMeta 作为其元 class,或明确指定 metaclass=ABCMeta


在你的例子中,继承自 PublisherSubscriber 已经将 Abstract 的元 class 设置为 ABCMeta,因此继承自 ABC 是多余的。从 Abstract 的基础 class 列表中删除 ABC,一切正常。

或者,如果你真的出于某种原因想要ABC在那里,你可以将它移到基础class列表的末尾,这将解决 MRO 冲突 - 首先说您希望 ABC 方法覆盖其他 classes 的方法,这与其他 classes 是子 [=38] 的事实相冲突=]es of ABC.