使用类方法实现抽象类不会引发异常



我试图将一个方法实现为抽象方法和类方法,但这样做并没有获得抽象类的任何好处。

例如:

from abc import ABC, abstractmethod
class BasePipeline(ABC):
@classmethod
@abstractmethod
def consume_frame(cls):
pass
@abstractmethod
def consume_frame_two(self):
pass
class AnotherSubclass(BasePipeline):
@classmethod
def does_nothing(cls):
a = 1 + 1
# Call it. 
AnotherSubclass.consume_frame()

这不会引发任何异常,也不会出错。我希望它能说一些类似于consume_frame_two is not implementedconsume_frame is not implemented的内容。

不确定预期的行为是什么,或者我是否只是做错了什么。如果AnotherSubclass.consume_frame()没有正确地实现为类方法,我希望它引发一个异常。

您的代码不会尝试创建AnotherSubclass类的实例。它所做的只是访问被标记为抽象的classmethod的实现。Python的ABC抽象类并不是为了阻止这种访问。

abc模块旨在帮助您定义协议接口,这是一个基类,用于设置对应该被视为相同的具体对象上必须存在哪些属性的期望。

为此,使用ABC子类所能做的就是防止创建类层次结构中至少有一个abstractmethodabstractproperty属性的任何类的实例。来自@abc.abstractmethod()文档:

具有从ABCMeta派生的元类的类不能实例化,除非它的所有抽象方法和属性都被重写。

任何abstractmethod修饰的方法都可以仍然被调用;没有防止这种情况的机制,并且具体实现可以使用CCD_ 13来访问CCD_。来自同一来源:

可以使用任何正常的"超级"调用机制来调用抽象方法

注意:与Java抽象方法不同,这些抽象方法可能有一个实现。这个实现可以通过super()机制从覆盖它的类中调用。在使用协作多重继承的框架中,这可能是超级调用的终点。

类的任何其他属性都可以像在其他类上一样使用,包括classmethod对象。

在封面下,每个ABCMeta元类都为您创建的每个类提供了一个__abstractmethods__属性,这是一个具有__isabstractmethod__属性设置为True的类上任何属性名称的frozenset对象,子类只需要使用与父抽象方法对象相同的名称,将其设置为未将__isabstractmethod__设置为true的属性,以从该类的集合中删除该名称。当您尝试创建__abstractmethods__不为空的类的实例时,Python将引发异常。

如果你需要进一步锁定你的类定义,那么你必须想出我们自己的元类或其他机制来实现这些规则。例如,您可以将classobject属性封装在自己的描述符对象中,以防止调用绑定到具有非空__abstractmethods__属性的类的类方法。

最新更新