[Python-3000] Metaclasses in Py3K

Josiah Carlson jcarlson at uci.edu
Sat Dec 16 23:47:10 CET 2006

Talin <talin at acm.org> wrote:
> Josiah Carlson wrote:
> > Talin <talin at acm.org> wrote:
> >> There's also Josiah Carlson's proposal which separates the 'metaclass' 
> >> function into two parts, the 'dict creation part' and the 'class 
> >> finishing part'.  (I.e. type= and dict=.) I would rather see them 
> >> unified, as it makes the class declaration syntax simpler, and it's easy 
> >> enough to write a metaclass that does one or the other or both.
> > 
> > The reason I offered a mechanism for separating them was because I don't
> > particularly like the idea of hitting the metaclass twice (particularly
> > a staticmethod, or base type assignment, which is just one more line of
> > code for people to forget, and makes metaclass/dictionary reuse more
> > restrictive), and because metaclasses, so far, haven't needed to be
> > classes. This particular proposal would make it so that metaclasses
> > would either need to be a class, or would need to assign to an attribute
> > on the function metaclass in order to overload the dictionary semantics.
> > Seems to be an unnecessary requirement.
> Most of the time, the only reason for adding a custom dict is so that 
> the metaclass can post-process it. The most common use case that I can 
> think of is a dict that remembers the order in which things were 
> defined; This by itself is not useful unless there's a metaclass that 
> can take advantage of that ordering information.

Maybe I'm strange, but I don't like the precreation/double calling
semantic. It just seems...sloppy?  It requires modification of all
current metaclasses to update to the new metaclass= syntax, just to
possibly support a single operation, which, according to the discussions
so far have but a single use-case: taking advantage of operation
ordering of assignments in the class namespace.

I'd rather not see class dictionary overloading than a metaclass
double-call semantic.

> So in other words, I don't see the two as independent at all. Yes, 
> technically they might be, but in terms of how metaclasses get used in 
> practice, I don't think they will be separate, and thus we're exposing 
> an unnecessary implementation detail and making class declarations more 
> cluttered than needed, in order to preserve a distinction that most 
> users won't care about.

It's not so much "to preserve a distinction that most users won't care
about", it's about not burdoning people who implement metaclasses with
functionality "that most users won't care about".  Think of it like a
doctor working on a patient; first do no harm.  If people think the
syntax is broken, fine, lets fix it, but lets also not break every
metaclass that exists just so that we can get functionality that very
few people want or need.  Seems like a waste to me.

> > Of course, then we still have __slots__.  Will the madness never end?
> I believe that with this new system, we'll eventually be able to 
> eliminate the need for __slots__. The metaclass can examine the 
> dictionary and create a '__slots__' member based on the decorators or 
> wrappers of the various values within the dict.

At the point of class creation, the only place where attributes of the
final instance are defined is within __init__, or any other callable
from __init__.  The removal of __slots__ by attempting to introspect on
the class namespace is either *really hard* or impossible.

Note that __slots__ removal, at least as they currently exist in the
Python cookbook, basically all rely on introspecting on the argument
list to __init__.  One looks for leading underscores __init__(self, _a,
_b), others use other semantics.  Many of them attempt to generalize on
problems such as...

    class point(object):
        __slots__ = ['x', 'y', 'z']
        def __init__(self, x, y, z):
            self.x = x
            self.y = y
            self.z = z

What makes it not generalizable is that things like the above is for one
fairly small set of use case that is not covered by any of the autoslots

> >> 4) Backwards compatibility
> >>
> >> It might be possible to retain backwards compatibility if desired. In 
> >> the proposed scheme, the metaclass is invoked twice - once to create the 
> >> dictionary, and once to 'finish' the class. Note that the second step is 
> >> identical to the operation of the current __metaclass__ feature.
> > 
> > Any syntax-based scheme is, by definition, not fully backwards
> > compatible.  The best we can hope for is for new functionality to not
> > work as intended in previous Pythons, but still be runnable.
> No, I'm talking about allowing the old __metaclass__ syntax to still 
> continue work in the new versions of Python. It won't have all the 
> functionality of the new syntax, but it will still work as it did before 
> - at least, until we decide to remove it.

That not backwards compatability of new features, it is forwards
compatability of old features.

 - Josiah

More information about the Python-3000 mailing list