In Python 2, with a trick it is possible to create a class with several bases, although the bases have metaclasses that are not subclass of each other.
The trick is that these metaclasses have themselves a metaclass (name it a "metametaclass"), and this metametaclass provides the metaclasses with a call method that dynamically creates a common sub-metaclass of the base metaclasses, if necessary. Eventually, a class results whose metaclass is the new sub-metaclass. Here is the code:
>>> class MetaMeta(type):
... def __call__(mcls, name, bases, methods):
... metabases = set(type(X) for X in bases)
... metabases.add(mcls)
... if len(metabases) > 1:
... mcls = type(''.join([X.__name__ for X in metabases]), tuple(metabases), {})
... return mcls.__new__(mcls, name, bases, methods)
...
>>> class Meta1(type):
... __metaclass__ = MetaMeta
...
>>> class Meta2(type):
... __metaclass__ = MetaMeta
...
>>> class C1:
... __metaclass__ = Meta1
...
>>> class C2:
... __metaclass__ = Meta2
...
>>> type(C1)
<class '__main__.Meta1'>
>>> type(C2)
<class '__main__.Meta2'>
>>> class C3(C1,C2): pass
...
>>> type(C3)
<class '__main__.Meta1Meta2'>
This example (of course changing the syntax to class C1(metaclass=Meta1)
etc) doesn't work in Python 3.
Question 1: Do I understand correctly that in Python 2, first C3
is constructed, using the metaclass of the first base, and an error would only result if type(C3)
were not a common subclass of type(C1)
and type(C2)
, whereas in Python 3 the error is raised earlier?
Question 2: (How) Is it possible to make the above example work in Python 3? I did try to use a subclass of abc.ABCMeta
as metametaclass, but even though using a custom __subclasscheck__
makes issubclass(Meta1, Meta2)
return True
, the creation of C3 would still result in an error.
Note: Of course I could make Python 3 happy by statically defining Meta1Meta2
and explicitly using it as a metaclass for C3
. However, that's not what I want. I want that the common sub-metaclass is created dynamically.
C3
by mixing togetherC1
andC2
's metaclasses explicitly? - mgilson