[Python-3000] Metaclasses in Py3K

Talin talin at acm.org
Sun Dec 17 01:18:13 CET 2006


Josiah Carlson wrote:
> 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 don't see why any existing metaclasses would need to be re-written - 
see below.

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

I see it as more of a "begin / end" kind of operation. One function gets 
called to begin the creation of a new class, the second gets called to 
finish it. I think of it as compilation - one operation creates a new 
template object, and the second one compiles it.

>>> 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
> implementations.

Slots can be done today, with the existing __metaclass__ syntax:

     class Slot:
         pass

     def slot_holder(name, bases, cdict):
         slots = []
         newdict = dict(__slots__=slots)
         for key, value in cdict.iteritems():
             if value is Slot:
                 slots.append( key )
             else:
                 newdict[ key ] = value

         return type(name, bases, newdict)

     class X:
         __metaclass__ = slot_holder
         x = y = z = Slot

         def __init__(self, x, y, z):
             self.x = x
             self.y = y
             self.z = z

     a = X( 1, 2, 3 )

>>>> 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.

Huh? I don't understand. In my lexicon, the term "backwards 
compatibility" generally means that existing code will continue to run 
on a new version of the interpreter and/or standard libraries.

As I see it, any class that uses the "__metaclass__ = foo" syntax would 
continue to work exactly like it does today - assuming we want it to. 
I'm basically saying that the new proposal and the existing system do 
not interfere with each other, and share some common implementation 
elements, that's all.

I don't see why you feel that all existing metaclasses would need to be 
re-written.

-- Talin


More information about the Python-3000 mailing list