Python 3.6 added PEP 487, which adds an __init_subclass__
method among other things. Is it possible to write a version of ABC
that doesn't use a metaclass?
If all you care about is the check for abstract methods, then yes. Just move the abstract method set computation to the __init_subclass__
method:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
# Compute set of abstract method names
abstracts = {name
for name, value in vars(cls).items()
if getattr(value, "__isabstractmethod__", False)}
for base in cls.__bases__:
for name in getattr(base, "__abstractmethods__", set()):
value = getattr(cls, name, None)
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name)
cls.__abstractmethods__ = frozenset(abstracts)
The base object.__new__
implementation then uses an non-empty __abstractmethods__
set to prevent instantiation.
But ABCs also support virtual subclass registration; the two hook methods this requires have to be implemented on the metaclass.