The reason is that type(name, bases, dict)
is not the right way to create class with specified metaclass.
Interpreter actually avoids calling type(name, bases, dict)
when in sees __metaclass__
attribute defined and calls mateclass instead of type(name, bases, dict)
as it would normally do.
Here is the relevant docs section that explains it:
When the class definition is read, if __ metaclass __ is defined then
the callable assigned to it will be called instead of type(). This
allows classes or functions to be written which monitor or alter the
class creation process [...]
If you modify your code like this:
class MetaA(type):
def __new__(cls, name, bases, attrs):
print "MetaA"
return super(MetaA, cls).__new__(cls, name, bases, attrs)
class A(object):
__metaclass__ = MetaA
class MetaB(MetaA):
def __new__(cls, name, bases, attrs):
print "MetaB"
return super(MetaB, cls).__new__(cls, name, bases, attrs)
class B(A):
__metaclass__ = MetaB
... then you'll get the expected output:
MetaA
MetaB
MetaA
(first line printed when creating class A, second and third when creating class B)
UPDATE: The question assumed dynamic creation of the class B
, so I'll extend my answer.
To construct the class B
with metacalss dynamically you should do the same thing as interpreter does, i.e. construct class with metaclass in __metaclass__
instad of type(name, bases, dict)
.
Like this:
B = MetaB('B', (A, ), {'__metaclass__': MetaB})