On May 30, 5:32 pm, LittleGrasshopper <seattleha...@yahoo.com> wrote: > On May 30, 4:01 pm, LittleGrasshopper <seattleha...@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.
That's correct. A type's metaclass has to be a not-necessarily proper superclass of the all the bases' metaclasses. Whenever possible type() will figure the most derived metaclass of all the bases and use that as the metaclass, but sometimes it can't be done. Consider the following: class AMeta(type): pass class A(object): __metaclass__ = AMeta class BMeta(type): pass class B(object): __metaclass__ = BMeta class C(A,B): pass # this will raise exception class CMeta(AMeta,BMeta): pass class C(A,B): __metaclass__ = CMeta # this will work ok > 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. I actually did rely on looking at the C source. There's a surprising amount of checking involving metaclass, layout, special methods, and so on that is involved when creating a new type. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list