solving the metaclass conflict
Michele Simionato
mis6 at pitt.edu
Sun Jun 8 07:34:12 EDT 2003
pje at telecommunity.com (Phillip J. Eby) wrote in message news:<25b5433d.0306071443.63b27df6 at posting.google.com>...
> mis6 at pitt.edu (Michele Simionato) wrote in message news:<2259b0e2.0306070629.7f5fcad7 at posting.google.com> <http://groups.google.com/groups?selm=2259b0e2.0306070629.7f5fcad7%40posting.google.com>...
> > I have just posted a recipe on the online Cookbook that could be of interest
> > for metaclasses users.
> >
> > ----------------------------------------------------------------------------
> >
> > Description:
> >
> > Any serious user of metaclasses has been bitten at least once by the
> > infamous metaclass/metatype conflict. Here I give a general recipe
^^^^^^
Here I have exaggerated a bit. I am aware my recipe has limitations:
that's why I call it a recipe! Notice that it fits in something like
25 lines,
skipping comments. It is general enough for that size.
>FYI, note that your implementation doesn't:
>* Handle classic classes in the base class list ('trivial()' should
>check for 'is ClassType' as well as 'is type')
This is on design:
1) I don't want people to use classic classes;
2) They will go away at some point;
3) They can be trivially converted to new-style classes with
a __metaclass__=type line at the beginning of the module.
Moreover, as you say, if one really wants it, it is trivial to fix it.
> * Handle non-type metatype roots (e.g. ExtensionClass and MESS)
I don't use this kind of stuff and they are not standard, so it was
not in the design to support them.
> * Handle multi-level metaclasses (e.g. metametaclasses)
True: look at the source code line
# create new metaclass,shift possible conflict to meta-metaclasses
return type(metaname,metabases,{})
The comments explicitly says that I don't want to fiddle with the
meta-metaclass
conflict. This could be done with a recursive version (something like
substituting 'type' here with 'clsfactory()(metaname,metabases,{})')
but I wanted to keep the recipe SIMPLE, I am not designing an
implementation for usage in core Python (even if I think somebody
should do that).
>* Remove unneeded metaclasses that are a subclass of another listed
>metaclass
Probably, as David says, you mean the reverse: one should remove
unneeded
metaclasses that are a superclass of another listed metaclass. Does
not seem
so dangerous, but I will fix it.
>* Reuse all generated metaclasses (You're memoizing on a set of base
>classes, rather than on the set of unique metaclasses.)
I am also memoizing the passed metaclasses (i.e. the 'metas' tuple)
and
from the tuple of bases classes I get the corresponding metaclasses,
so
it is not obvious when _generatemetaclass will fail. Can you give a
counterexample ? If yes, I will fix it.
> PEAK's 'peak.util.Meta' module contains a more-complete implementation
> of this technique. (See <http://peak.telecommunity.com/> for info on
> PEAK.)
I will look at it.
>It's bloody difficult to write a correct, complete, and efficient
>metaclass generator, so it's no wonder Guido chose to punt on this in
>2.2 (and 2.3 for that matter).
I would say it is difficult, indeed. Maybe not bloody difficult,
though.
I think may recipe is good enough for most users, especially since
they
can understand how it works and its limitations (which were indicated
in the commented lines BTW; I don't think meta-metaclasses are so
largely used to deserve explicit mention). Anyway, I will fix the
issue
with meta-metaclasses if it can be done with few lines of code, and
the issue with unneeded metaclasses, too. Not sure if I want to fix
the
issue with classic classes, tough.
Thanks for the feedback, it is what I asked for.
Michele
More information about the Python-list
mailing list