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