Here is a python session.
>>> class Z(type):
def __new__(cls, name, bases, attrs):
print cls
print name
return type(name, bases, attrs)
...
>>> class Y(object):
__metaclass__ = Z
...
<class '__main__.Z'>
Y
>>> class X(Y):
... pass
...
>>> class W(Y):
... __metaclass__ = Z
...
<class '__main__.Z'>
W
>>>
After I define class X I expect Z._new__ to be called for it, and to print the two line, which is not happening, (as metaclass are inherited?)
The problem is that the cls
argument (which is the metaclass object) is not passed on when you call type
, therefore the class object Y
that is created and returned does not have any reference to the metaclass Z
.
If you replace the last line in __new__
with
return super(Z, cls).__new__(cls, name, bases, attrs)
then it works. Note that even though cls
is used in super
we still have to provide cls
as an argument as well, since super
here returns an unbound method (see here for more).
As an alternative to using super one could use:
return type.__new__(cls, name, bases, attrs)
The important thing is that we give cls
(our metaclass object Z
) to the classmethod __new__
. The shorter form type(name, bases, attrs)
fills in type
itself for the cls
argument, which is of course wrong. This error is similar to calling an instance method with the wrong self
argument.
I prefer using super
, since this is better style.