Re: Choosing a Metaclass?
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__ (,) >>> MetaWrapper.__metaclass__ >>> dir(MyMeta) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__'] >>> MetaWrapper.__new__ 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__ (,) >>> MetaWrapper.__metaclass__ >>> 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__ >>> 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
Re: Choosing a Metaclass?
Never mind, I've figured it out. The build_class function looks at the '__class__' attribute of the first base class if there's no explicit __metaclass__ attribute. By calling type directly, the __class__ attribute as returned by MyMeta is, in fact, type. Should have just looked at the source to begin with. On 2/21/08, Jeff McNeil <[EMAIL PROTECTED]> 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? > > Thanks! > > Jeff > > -- http://mail.python.org/mailman/listinfo/python-list
Choosing a Metaclass?
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? Thanks! Jeff -- http://mail.python.org/mailman/listinfo/python-list