class MyMeta(type):
def __new__(meta, cls, bases, attributes):
print 'MyMeta.__new__'
return type.__new__(meta, cls, bases, attributes)
def __init__(clsobj, cls, bases, attributes):
print 'MyMeta.__init__'
class MyClass(object):
__metaclass__ = MyMeta
foo = 'bar'
Another way to achieve the same result:
cls = "MyClass"
bases = ()
attributes = {'foo': 'bar'}
MyClass = MyMeta(cls, bases, attributes)
MyMeta
is a callable so Python will use the special method __call__
.
Python will look for __call__
in the MyMeta
's type (which is type
in our case)
"For new-style classes, implicit invocations of special methods are
only guaranteed to work correctly if defined on an object’s type, not
in the object’s instance dictionary"
MyClass = MyMeta(...)
is interpreted as:
my_meta_type = type(MyMeta)
MyClass = my_meta_type.__call__(MyMeta, cls, bases, attributes)
Inside the type.__call__()
I imagine something like this:
MyClass = MyMeta.__new__(MyMeta, cls, bases, attributes)
meta_class = MyClass.__metaclass__
meta_class.__init__(MyClass, cls, bases, attributes)
return MyClass
MyMeta.__new__()
will decide how the MyClass
is built:
type.__new__(meta, cls, bases, attributes)
will set the correct metaclass (which is MyMeta
) for MyClass
type(cls, bases, attributes)
will set the default metaclass (which is type) for MyClass