[Python-Dev] Metatype conflict among bases?

Phillip J. Eby pje@telecommunity.com
Tue, 22 Apr 2003 18:31:24 -0400


David Abrahams <dave@boost-consulting.com> wrote:
 >
 >Consider:
 >
 >    class A(object):
 >        class __metaclass__(type):
 >            pass
 >
 >    class B(A):  # TypeError: metatype conflict among bases
 >        class __metaclass__(type):
 >            pass
 >
 >Now that's a weird error message at least!  There's only one base (A),
 >and I'm telling Python explicitly to use the nested __metaclass__
 >instead of A's __metaclass__!
 >
 >Should I not be surprised that Python won't let me set the metatype
 >explicitly?

The problem here is that B.__metaclass__ *must* be the same as, or a 
subclass of, A.__metaclass__, or vice versa.  It doesn't matter whether the 
metaclass is specified implicitly or explicitly, this constraint must be 
met.  Your code doesn't meet this constraint.  Here's a revised example 
that does:

     class A(object):
         class __metaclass__(type):
             pass

     class B(A):
         class __metaclass__(A.__class__):
             pass

B.__metaclass__ will now meet the "metaclass inheritance" constraint.  See 
the "descrintro" document for some more info about this, and the "Putting 
Metaclasses To Work" book for even more info about it than you would ever 
want to know.  :)

Here's a short statement of the constraint, though:

A class X's metaclass (X.__class__) must be identical to, or a subclass of, 
the metaclass of *every* class in X.__bases__.  That is:

for b in X.__bases__:
     assert X.__class__ is b.__class__ or issubclass(X.__class, b.__class__),\
         "metatype conflict among bases"