Python3 - 如何从现有抽象类定义抽象子类?

Posted

技术标签:

【中文标题】Python3 - 如何从现有抽象类定义抽象子类?【英文标题】:Python3 - How does one define an abstract subclass from an existing abstract class? 【发布时间】:2018-07-26 14:54:44 【问题描述】:

我最初定义了以下抽象类:

from abc import ABC, abstractmethod    
class Primitive(ABC):

现在我想创建另一个继承自 Primitive 的抽象类:

class InstrumentName(Primitive)

我需要这个类是抽象的,因为我最终想要创建以下两个具体类:

class CurrencyInstrumentName(InstrumentName)
class MetalInstrumentName(InstrumentName)

我已阅读文档并搜索了 SO,但它们主要涉及从抽象类中子类化具体类,或讨论 Python 如何处理抽象

【问题讨论】:

【参考方案1】:

只是子类,你不需要做任何特别的事情。

只有在实现中没有更多 abstractmethodabstractproperty 对象时,类才会变得具体。

让我们来说明一下:

from abc import ABC, abstractmethod    
class Primitive(ABC):
    @abstractmethod
    def foo(self):
        pass

    @abstractmethod
    def bar(self):
        pass

class InstrumentName(Primitive):
    def foo(self):
        return 'Foo implementation'

这里,InstrumentName 仍然是抽象的,因为bar 被保留为abstractmethod。您不能创建该子类的实例:

>>> InstrumentName()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class InstrumentName with abstract methods bar

子类也可以根据需要添加@abstractmethod@abstractproperty方法。

在底层,所有子类都继承了强制执行此操作的 ABCMeta 元类,它只是检查类中是否还有任何 @abstractmethod@abstractproperty 属性。

【讨论】:

所以我应该忽略 PyCharm 的警告,即我没有为 InstrumentName 提供具体实现? @EbramShehata 是的。 PyCharm 试图提供帮助,但无法知道您有意创建抽象基类的层次结构。但这是一件非常合理的事情! 是否有可能从type 元类中进行abstractmethod 检测?这样就不需要ABCMeta 元类。 (我说的是语言设计。)换句话说,ABCMeta 做的事情是type 做不到的? @Maggyero:当然,但这会给所有类型增加很多含义。 ABCMeta 还处理虚拟子类注册,它在子类化时增加了少量开销(合并基类的__abstractmethods__ 集)等。从设计角度来看,ABC 是一个需要选择加入的单独功能。如果type 实现了这一点,您将不再选择加入。 好的开销。对于选择加入要求(通过选择加入,我假设您是指用户的故意选择——我不是以英语为母语的人),我认为定义抽象基类的意图从抽象的存在中已经很清楚了方法。对我来说感觉不是很DRY(不要重复自己),更像是 WET(所有内容都写两次)解决方案。【参考方案2】:

正如@MartijnPieters 所写,您不需要为 Python 做任何特别的事情,但 PyCharm 会发出警告:

类 InstrumentName 必须实现所有抽象方法

抑制该警告的一种方法:

import abc

class Primitive(abc.ABC):
    @abc.abstractmethod
    def foo(self):
        pass

# noinspection PyAbstractClass
class InstrumentName(Primitive):
    def is_tuba(self):
        return False

另一种方式:

...

class InstrumentName(Primitive, metaclass=abc.ABCMeta):
    def is_tuba(self):
        return False

【讨论】:

以上是关于Python3 - 如何从现有抽象类定义抽象子类?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的抽象类abstract

2继承抽象类

继承抽象类

继承抽象类

Java 中的抽象类及接口

java_抽象类