На самом деле проблема связана с __new__
, а не с __init__
. Пример:
from abc import ABCMeta, abstractmethod
from collections import OrderedDict
class Foo(metaclass=ABCMeta):
@abstractmethod
def foo(self):
return 42
class Empty:
def __init__(self):
pass
class C1(Empty, Foo): pass
class C2(OrderedDict, Foo): pass
C1()
завершается с ошибкой TypeError
, как ожидалось, а C2.foo()
возвращает 42
.
>>> C1.__init__
<function Empty.__init__ at 0x7fa9a6c01400>
Как видите, он не использует object.__init__
и даже не вызывает суперкласс (object
) __init__
Вы можете проверить это, позвонив __new__
самостоятельно:
C2.__new__(C2)
работает просто отлично, в то время как вы получите обычный TypeError
с C1.__new__(C1)
Итак, imho, он не такой четкий, как
если вы хотите абстрактный базовый класс, все его базы должны быть абстрактными.
Хотя это хорошее предложение, обратное утверждение не обязательно верно: ни OrderedDict
, ни Empty
не являются абстрактными, и все же подкласс первого является "конкретным", а последний "абстрактным"
Если вам интересно, я использовал OrderedDict
в примере вместо list
, потому что последний является «встроенным» типом, и, таким образом, вы не можете сделать:
OrderedDict.bar = lambda self: 42
И я хотел прямо заявить, что проблема не связана с ним.