You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The appropriate metaclass for a class definition is determined as follows:
if no bases and no explicit metaclass are given, then :func:type is used;
if an explicit metaclass is given and it is not an instance of
:func:type, then it is used directly as the metaclass;
if an instance of :func:type is given as the explicit metaclass, or
bases are defined, then the most derived metaclass is used.
The most derived metaclass is selected from the explicitly specified
metaclass (if any) and the metaclasses (i.e. type(cls)) of all specified
base classes. The most derived metaclass is one which is a subtype of all
of these candidate metaclasses. If none of the candidate metaclasses meets
that criterion, then the class definition will fail with TypeError.
So according to that, the metaclass of D in this code
should be Mx as it's the most derived of all candidates (M1, M2, Mx). But instead the cpython exitis with
class D(A2, B1, C1): pass
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
This piece of docs seems to origin from way back in 2005, issue #42380
As said above, I'm not even sure what the actually algorithm is that determines the implicit metaclass. From my experimentation, I assume it's:
If there's an explicit metaclass, it is checked to be a sub-class of the metaclass of each parent
If there's no explicit metaclass, the parents are checked from left to right:
When a new metaclass is encountered, it is checked to be a sub-class of the previous implicit metaclass and, if it is, set as the new implicit metaclass.
If not a fix of the docs, I'd be really happy about somebody enlightening me about how the interpreter handles the resolution (or rather how it's supposed to handle it), as this would unblock my work over at mypy.
If there's no explicit metaclass, the parents are checked from left to right:
When a new metaclass is encountered, it is checked to be a sub-class of the previous implicit metaclass and, if it is, set as the new implicit metaclass.
Documentation
I'm not 100% sure if this is an issue with the docs or the interpreter. But it's evident that the docs don't match what the interpreter does.
The docs say here:
So according to that, the metaclass of
D
in this codeshould be
Mx
as it's the most derived of all candidates (M1
,M2
,Mx
). But instead the cpython exitis withNote that
class D(A2, C1, B1): pass
works.Some additional context:
As said above, I'm not even sure what the actually algorithm is that determines the implicit metaclass. From my experimentation, I assume it's:
Linked PRs
The text was updated successfully, but these errors were encountered: