Если вы не используете abc.ABCMeta
в качестве метакласса для вашего класса (явно или наследуя от abc.ABC
), использование abstractmethod
на самом деле ничего не делает.
>>> from abc import abstractmethod, ABC
>>> class Foo:
... @abstractmethod
... def bar(self):
... pass
...
>>> f = Foo()
>>>
Аналогично, использование ABCMeta
мало что значит, если вы не пометите хотя бы один метод как абстрактный:
>>> class Bar(ABC):
... pass
...
>>> b = Bar()
>>>
Это комбинация двух, которая позволяет (номинально) классу быть нереализуемым:
>>> class Baz(ABC):
... @abstractmethod
... def m(self):
... pass
...
>>> b = Baz()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Baz with abstract methods m
>>>
(Даже в этом случае обратите внимание, что все, что делает @abstractmethod
, это добавляет декорированный метод к набору, к которому обращается механизм метакласса при попытке создания экземпляра класса. Победить этот механизм тривиально:
>>> Baz.__abstractmethods__
frozenset({'m'})
>>> Baz.__abstractmethods__ = set()
>>> b = Baz()
>>>
)
Обратите внимание, что ABC
сам по себе является тривиальным классом, который использует ABCMeta
в качестве метакласса, что заставляет его использовать любой из его потомков.
# Docstring omitted; see
# https://github.com/python/cpython/blob/3.7/Lib/abc.py#L166
# for the original
class ABC(metaclass=ABCMeta):
__slots__ = ()