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】:只是子类,你不需要做任何特别的事情。
只有在实现中没有更多 abstractmethod
和 abstractproperty
对象时,类才会变得具体。
让我们来说明一下:
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 - 如何从现有抽象类定义抽象子类?的主要内容,如果未能解决你的问题,请参考以下文章