On Sat, 17 Sep 2005 12:41:09 -0300, Pedro Werneck <[EMAIL PROTECTED]> wrote:
>On 17 Sep 2005 02:04:39 -0700 >"Simon Percivall" <[EMAIL PROTECTED]> wrote: > >> Have you read the "Metaclasses" part of "Unifying types and classes in >> Python 2.2"? (http://www.python.org/2.2.3/descrintro.html#metaclasses) > >Yes, I read. Have you read and understood my message ? :) > >A class B, subclass of class A, with a metaclass M_A should have M_A or >a subclass of it as metaclass. If you try with anything else, you get a >TypeError exception as expected. OK. But if you try with 'type', nothing >happens. > >Python 2.4.1 (#1, Sep 16 2005, 17:47:47) >[GCC 3.3.4] on linux2 >Type "help", "copyright", "credits" or "license" for more information. >>>> class M_A(type): pass >... >>>> class A: __metaclass__ = M_A >... >>>> class B(A): __metaclass__ = type >... >>>> B.__class__ ><class '__main__.M_A'> >>>> B.__metaclass__ ><type 'type'> > FWIW, I think __metaclass__ can be any callable, but it seems to be the first argument to type.__new__ that invokes the checking and type(name, bases, cdict) seems to have the same effect as type.__new__(type, name, bases, cdict). Maybe there has to be a "real" class on the mro, and type isn't one, or it's a wild card ;-) I haven't really grokked the error message's true meaning, not having dealt with metaclass conflict before. Not ready today, sorry ;-) >>> class M_A(type): pass ... >>> class A: __metaclass__ = M_A ... >>> def foo(*args): print args; return 'silliness' ... >>> def foo(cname, cbases, cdict): ... print 'cname, cbases:', cname, cbases ... print 'cdict:', cdict ... mt = type('M_B',(type,),{}) ... print 'mt:', mt ... print 'mt.mro(mt):', mt.mro(mt) ... print 'mt.__new__:', mt.__new__ ... something = mt.__new__(mt, cname, cbases, cdict) ... print 'something:', something ... return something ... >>> class B(A): __metaclass__ = foo ... cname, cbases: B (<class '__main__.A'>,) cdict: {'__module__': '__main__', '__metaclass__': <function foo at 0x02EEBD84>} mt: <class '__main__.M_B'> mt.mro(mt): [<class '__main__.M_B'>, <type 'type'>, <type 'object'>] mt.__new__: <built-in method __new__ of type object at 0x1E1BF670> Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 8, in foo TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases >>> def bar(cname, cbases, cdict): ... print 'cname, cbases:', cname, cbases ... print 'cdict:', cdict ... mt = type ... print 'mt:', mt ... print 'mt.mro(mt):', mt.mro(mt) ... print 'mt.__new__:', mt.__new__ ... something = mt.__new__(mt, cname, cbases, cdict) ... print 'something:', something ... return something ... >>> class B(A): __metaclass__ = bar ... cname, cbases: B (<class '__main__.A'>,) cdict: {'__module__': '__main__', '__metaclass__': <function bar at 0x02EEBDF4>} mt: <type 'type'> mt.mro(mt): [<type 'type'>, <type 'object'>] mt.__new__: <built-in method __new__ of type object at 0x1E1BF670> something: <class '__main__.B'> >>> And the something returned, whatever it is, if no checking is triggered by normal use, gets bound to the class name, e.g., >>> class C(A): __metaclass__ = lambda *a:('silly', 'result') ... >>> C ('silly', 'result') Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list