Metaclass mystery

LittleGrasshopper seattlehanks at yahoo.com
Sat May 30 20:32:33 EDT 2009


On May 30, 4:01 pm, LittleGrasshopper <seattleha... at yahoo.com> wrote:
> I am experimenting with metaclasses, trying to figure out how things
> are put together. At the moment I am baffled by the output of the
> following code:
>
> ************************************
> """
> Output is:
>
> instance of metaclass MyMeta being created
> (<class '__main__.MyMeta'>, <class '__main__.MyMeta'>)
> instance of metaclass MyNewMeta being created
> instance of metaclass MyMeta being created   <<<< Why this?
> (<class '__main__.MyMeta'>, <class '__main__.MyNewMeta'>)
>
> """
>
> class MyMeta(type):
>     def __new__(meta, classname, bases, classDict):
>         print 'instance of metaclass MyMeta being created'
>         return type.__new__(meta, classname, bases, classDict)
>
> class MyNewMeta(type):
>     def __new__(meta, classname, bases, classDict):
>         print 'instance of metaclass MyNewMeta being created'
>         return type(classname, bases, classDict)
>
> """
> Notice that a metaclass can be a factory function:
> def f(classname, bases, classDict):
>     return type(classname, bases, classDict)
>
> class MyClass(object):
>     __metaclass__ = f
> """
>
> class MyClass(object):
>     __metaclass__ = MyMeta
>
> print (MyClass.__class__, MyClass.__metaclass__)
>
> class MySubClass(MyClass):
>     __metaclass__ = MyNewMeta
>
> print (MySubClass.__class__, MySubClass.__metaclass__)
> ************************************
> Honestly, I don't know why this line:
> instance of metaclass MyMeta being created   <<<< Why this?
> is being output when the MySubClass class object is instantiated.
> MyNewMeta's __new__ method simply instantiates type directly (which I
> know shouldn't be done, but I'm just experimenting and trying to
> understand the code's output.)
>
> I would really appreciate some ideas.

This is my working theory:

return type(classname, bases, classDict), in MyNewMeta.__new__(),
actually calls type.__new__(type, classname, bases, classDict). I
think the magic happens in this method call. This method must look at
bases and notice that MySubClass extends MyClass, and that MyClass'
type is MyMeta, so instead of instantiating a 'type' object it decides
to instantiate a 'MyMeta' object, which accounts for the output.

Seriously, metaclasses are making my brain hurt. How do people like
Michele Simionato and David Mertz figure these things out? Does it all
come to looking at the C source code for the CPython interpreter?

Brain hurts, seriously.



More information about the Python-list mailing list