I have two questions converning metaclasses and multiple inheritance. The first is: Why do I get a TypeError for the class Derived
but not for Derived2
?
class Metaclass(type): pass
class Klass(object):
__metaclass__ = Metaclass
#class Derived(object, Klass): pass # if I uncomment this, I get a TypeError
class OtherClass(object): pass
class Derived2(OtherClass, Klass): pass # I do not get a TypeError for this
The exact error message is:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases object, Klass
The second question is: Why does super
not work in this case(if I use __init__
instead of __new__
, super
works again):
class Metaclass(type):
def __new__(self, name, bases, dict_):
return super(Metaclass, self).__new__(name, bases, dict_)
class Klass(object):
__metaclass__ = Metaclass
There I get:
TypeError: Error when calling the metaclass bases type.__new__(X):
X is not a type object (str)
I'm using Python 2.6.
For the first question, have a look at the description of MRO in python - specifically, the "bad Method Resolution order" section. Essentially, it's to do with the fact that python doesn't know whether to use object or Klass's methods. (It's nothing to do with the usage of metaclasses.)
For the second question, it looks like you're misunderstanding how the
__new__
function works. It doesn't take a reference to itself as the first argument - it takes a reference to the type of the class being instantiated. So your code should look like this:Why would you do?
Klass already derives from object.
Is the reasonable thing here.
The second question has already been well answered twice, though
__new__
is actually a staticmethod, not a classmethod as erroneously claimed in a comment...:The first question (as somebody noted) has nothing to do with metaclasses: you simply can't multiply inherit from any two classes A and B in this order where B is a subclass of A. E.g.:
The MRO guarantees that leftmost bases are visited before rightmost ones - but it also guarantees that among ancestors if x is a subclass of y then x is visited before y. It's impossible to satisfy both of these guarantees in this case. There's a good reason for these guarantees of course: without them (e.g. in old style classes, which only guarantee the left-right order in method resolution, not the subclass constraint) all overrides in x would be ignored in favor of the definitions in y, and that can't make much sense. Think about it: what does it mean to inherit from
object
first, and from some other class second? Thatobject
's (essentially nonexistent;-) definition of its several special methods must take precedence over the other class's, causing the other class's overrides to be ignored?For the second question, you need to pass self to
__new__
like this:I can't recall off the top of my head why this is, but I think it's because
type.__new__
isn't a bound method and thus doesn't magically get the self argument.