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?
Asked
Active
Viewed 173 times
1

Neil G
- 32,138
- 39
- 156
- 257
-
If all you care about is the check for abstract methods, then yes. But abcs also support [virtual subclass registration](https://docs.python.org/3/library/abc.html#abc.ABCMeta.register). – Martijn Pieters Jul 07 '17 at 18:09
-
@MartijnPieters Yes, I meant to specify that all I care about is the check for abstract methods. – Neil G Jul 07 '17 at 18:11
-
Is this about writing an alternative to the standard library `ABC`, or about how to use the existing `ABC`? – Håken Lid Jul 07 '17 at 18:15
-
1@HåkenLid An alternative. The problem with metaclasses in Python is that as soon as I have more than one in my inheritance tree, I have to start composing the metaclasses, which is annoying. However, I would like to use the abstractmethod functionality. – Neil G Jul 07 '17 at 18:16
1 Answers
3
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.

flornquake
- 3,156
- 1
- 21
- 32

Martijn Pieters
- 1,048,767
- 296
- 4,058
- 3,343
-
-
okay, and then can you block instantiation in `__new__` if there are leftover abstract methods without using a metaclass? – Neil G Jul 07 '17 at 18:21
-
1@NeilG: sorry, the base `object.__new__` implementation does this already. – Martijn Pieters Jul 07 '17 at 18:35