ahui ahui - 3 years ago 132
Python Question

Why does metaclass with object base raise metaclass conflict?

Why in the code below does metaclass with object base raise metaclass conflict exception?


"metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases"


class M_A(object): pass
class A(object, metaclass = M_A): pass


So does another code:

class M_A(list): pass
class A(object, metaclass = M_A): pass


I understand that the cpython will interpret the above code as:

A = M_A.__new__(M_A, 'A', (object,), {})


What confuses me is that the base class of A is object, and any class is subclass of object. This error is so strange.
What's wrong with me?

Answer Source

Let's take a closer look at this error message:

metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

This is a little confusing, so let's take a look at what's what:

  • The "derived class" is A.
  • The "metaclass of a derived class" A is M_A.
  • A's base class is object, therefore "the metaclasses of all its bases" is type - because type is object's metaclass.

This is the problem - object's metaclass is type, but A's metaclass is M_A. Since M_A isn't a subclass of type, python doesn't know which metaclass to use for A and throws an error.


To fix this, change the parent class of M_A to type:

class M_A(type): pass
class A(object, metaclass = M_A): pass

# no errors thrown
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download