PEP 3119声明:
但是,我无法找到解释原因的原因。具体来说,我没有注意到在未明确继承
@abstractmethod
装饰器只应在类体内使用,并且仅适用于其元类是(派生自)ABCMeta
的类。不支持动态地将抽象方法添加到类中,或者尝试在创建方法或类时修改其抽象状态。
@abstractmethod
的类中仅使用ABCMeta
时的行为差异。在下面的简单示例中,如果我理解正确,正确的做法是:
import six
from abc import ABCMeta
from abc import abstractmethod
class Base(six.with_metaclass(ABCMeta)):
def __init__(self):
print('Init abstract base')
@abstractmethod
def do_something(self):
pass
class Subclass(Base):
def __init__(self):
super(Subclass, self).__init__()
def do_something(self):
print('Done.')
sub = Subclass()
sub.do_something()
但是,如果我让Base
类仅从object
继承,并且只在需要时使用装饰器,我注意到行为没有变化。
from abc import abstractmethod
class Base(object):
def __init__(self):
print('Init abstract base')
@abstractmethod
def do_something(self):
pass
class Subclass(Base):
def __init__(self):
super(Subclass, self).__init__()
def do_something(self):
print('Done.')
sub = Subclass()
sub.do_something()
我发现即使在更复杂的架构上也是如此,所以我想知道:后一种方法什么时候失败?
答案 0 :(得分:1)
您没有看到任何差异,因为您的第一个子类确实实现了do_something
abstractmethod。
在两个版本的子类中注释掉do_something
的定义,你会发现在第一种情况下,当你试图实现子类时,你得到一个TypeError
- 你也会得到一个试图实现第一个版本Base
类本身的FWIW。使用第二个版本,您可以实现两个类(这不应该是可能的,因为它们是抽象的)并调用抽象的do_something
方法 - 哪种方法会破坏ABCs的一个主要点。
你也会错过ABC FWIW的其他一些有趣的功能......