Another way to spell __metaclass__ ?
Michele Simionato
mis6 at pitt.edu
Fri Dec 13 11:21:26 EST 2002
bokr at oz.net (Bengt Richter) wrote in message news:<atbtha$959$0 at 216.39.172.122>...
> I must confess there is something that bothers me about __metaclass__ as
> an impementation of metaclass functionality. It strikes me more as a
> class transmogrification hook with a debug/trace flavor than a clear expression
> of the relationship between two classes, one of which produces the other
> as an instance.
>
> I.e., to me, the hallmark of a metaclass is that it produces another class when
> instantiated (normally with variations based on conditions or parameters, or why
> do it).
I understand what you are saying and I am sympathetic with you.
> Below is an example experiment, viewing a metaclass as a class that will create
> another class as its instance, but by retrieving prototype class elements from
> an existing ordinary class instead of having it transmitted by an event at the
> end of the latter class definition execution (protoclass below is just a helper).
>
> >>> def protoclass(cls):
> ... """return cls, name, bases, cdict copies like __metaclass__ parameters"""
> ... return cls, cls.__name__, cls.__bases__, cls.__dict__.copy()
> ...
> >>> class MCExample(type):
> ... def __new__(cls, proto, *args):
> ... pccls, pcname, pcbases, pcdict = protoclass(proto)
> ... pcdict['params'] = args # minimal parameterization
> ... return type.__new__(cls, pcname+'_mod_'+cls.__name__, pcbases, pcdict)
> ...
> >>> class P(object):
> ... classvar = 'P classvar'
> ... def foo(self, x): print 'Hello from prototype foo, called with %s' % x
> ...
> >>> C = MCExample(P, 123, 'some metaclass args', 456)
> >>> C
> <class '__main__.P_mod_MCExample'>
> >>> c=C()
> >>> c
> <__main__.P_mod_MCExample object at 0x0079E520>
> >>> c.classvar
> 'P classvar'
> >>> c.foo('spam')
> Hello from prototype foo, called with spam
> >>> c.params
> (123, 'some metaclass args', 456)
> >>> c.__class__
> <class '__main__.P_mod_MCExample'>
> >>> c.__class__.__class__
> <class '__main__.MCExample'>
> >>> c.__class__.__class__.__class__
> <type 'type'>
>
> This allows the use of the prototype as an ordinary class as well:
>
> >>> p = P()
> >>> p.classvar
> 'P classvar'
> >>> p.foo('eggs')
> Hello from prototype foo, called with eggs
>
> But since p is a P instance, not a P_mod_MCExample instance, we don't find params:
>
> >>> p.params
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: 'P' object has no attribute 'params'
>
> >>> p.__class__
> <class '__main__.P'>
> >>> p.__class__.__class__
> <type 'type'>
>
You can also see my new posting on class factory functions.
> This is just a preliminary experiment to see how the semantics feel looking from the
> other direction. IOW, you just use the metaclass like an ordinary class that happens
> to produce another class, using a prototype class as a starting point, except the
> metaclass expresses the link to the prototype, not the other way around. There is no
> __metaclass__ attribute in the prototype class.
>
This is interesting enough. I thought the __metaclass__ hook was
automatically created but now I see that this is not the case.
> Regards,
> Bengt Richter
Regards,
Michele
More information about the Python-list
mailing list