Jeff McNeil wrote: > Hi list, > > Hopefully a quick metaclass question. In the following example, MyMeta > is a metaclass that does not inherit directly from type: > > #!/usr/bin/python > > class MyMeta(object): > def __new__(cls, name, bases, vars): > print "MyMeta.__new__ called for %s" % name > return type(name, bases, vars) > > class MetaWrapper(object): > __metaclass__ = MyMeta > > class M(MetaWrapper): > pass > > [EMAIL PROTECTED] ~]$ python t.py > MyMeta.__new__ called for MetaWrapper > [EMAIL PROTECTED] ~]$ > > When I run that script, it's apparent that although M inherits from > MetaWrapper, it does not use MyMeta as it's metaclass. However, if I > change MyMeta to be a subclass of builtin type, it works as I would expect: > > [EMAIL PROTECTED] ~]$ cat t.py > #!/usr/bin/python > > class MyMeta(type): > def __new__(cls, name, bases, vars): > print "MyMeta.__new__ called for %s" % name > return super(MyMeta, cls).__new__(cls, name, bases, vars) > > class MetaWrapper(object): > __metaclass__ = MyMeta > > class M(MetaWrapper): > pass > > [EMAIL PROTECTED] ~]$ python t.py > MyMeta.__new__ called for MetaWrapper > MyMeta.__new__ called for M > [EMAIL PROTECTED] ~]$ > > How exactly does Python choose which MC it will use when building a > class? It doesn't seem to me that the parent class of MyMeta should > matter in this case? > When you create a subclass M of MetaWrapper in your first example, MetaWrapper is a subclass of object that has no metaclass of its own, and therefore it resolves __new__() from object:
>>> MetaWrapper.__bases__ (<type 'object'>,) >>> MetaWrapper.__metaclass__ <class '__main__.MyMeta'> >>> dir(MyMeta) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__'] >>> MetaWrapper.__new__ <built-in method __new__ of type object at 0x6cb92f50> In your second example MyMeta is a subclass of type, and therefore it resolves type's __new__(), which is what takes the special actions you observe when a subclass is defined: >>> MetaWrapper.__bases__ (<type 'object'>,) >>> MetaWrapper.__metaclass__ <class '__main__.MyMeta'> >>> dir(MyMeta) ['__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__cmp__', '__delattr__', '__dict__', '__dictoffset__', '__doc__', '__flags__', '__getattribute__', '__hash__', '__init__', '__itemsize__', '__module__', '__mro__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasses__', '__weakrefoffset__', 'mro'] >>> MetaWrapper.__new__ <built-in method __new__ of type object at 0x6cb92f50> >>> Hope this helps. Remember that when there is no __metaclass__ defined in a class's body (and the module namespace has no default __metaclass__) the class's metaclass is the type of the class's first base class. regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list