In a file named exp.py (below), I am trying to understand metaclasses in Python. It seems like when the metaclass's __new__
method uses the 'type' constructor to construct a class, its __new__
method does not get called by a subclass of a class using it as the metaclass:
class A(type):
def __new__(cls, name, bases, dct):
print "cls is: ", cls
print "name is: ", name
print "bases is: ", bases
print "dct is: ", dct
print
return super(A, cls).__new__(cls, name, bases, dct)
class B(object):
__metaclass__ = A
class C(B): pass
class D(type):
def __new__(cls, name, bases, dct):
print "cls is: ", cls
print "name is: ", name
print "bases is: ", bases
print "dct is: ", dct
return type(name, bases, dct)
class E(object):
__metaclass__ = D
class F(E): pass
In the terminal:
>>> from exp import *
cls is: <class 'exp.A'>
name is: B
bases is: (<type 'object'>,)
dct is: {'count': 0, '__module__': 'exp', '__metaclass__': <class 'exp.A'>, '__init__': <function __init__ at 0x107eb9578>}
cls is: <class 'exp.A'>
name is: C
bases is: (<class 'exp.B'>,)
dct is: {'__module__': 'exp'}
cls is: <class 'exp.D'>
name is: E
bases is: (<type 'object'>,)
dct is: {'count': 0, '__module__': 'exp', '__metaclass__': <class 'exp.D'>, '__init__': <function __init__ at 0x107ebdb18>}
>>>
As you can see, the __new__
method of the metaclass D does not get called when class F's definition is loaded. (If it had been called, then information about the class F would have been printed too.)
Could someone help me explain this?
Related post: I was reading What is a metaclass in Python?, and seem to encounter something similar in the sentence, "Be careful here that the __metaclass__
attribute will not be inherited, the metaclass of the parent (Bar.__class__
) will be. If Bar used a __metaclass__
attribute that created Bar with type()
(and not type.__new__()
), the subclasses will not inherit that behavior." But I did not fully understand this.