[Python-3000] super(), class decorators, and PEP 3115

Phillip J. Eby pje at telecommunity.com
Mon Apr 30 20:46:47 CEST 2007


While working on the generic function PEP, I came across an unexpected (to 
me, anyway) consequence of PEP 3115: it breaks current methods (circa 
Python 2.2+) of implementing class decorators.  However, there does not 
appear to be a class decorator PEP outstanding.

In current Python versions, the only way to implement class decorators is 
to call a "magic" function in the body of the class, that inserts a special 
(temporary) metaclass to handle the decoration.  This is implemented in the 
DecoratorTools package as well as in zope.interface (where its most common 
use case is to supply interface information about a class).

Of course, in Py 3.x, some of these features could be handled using a 
metaclass with keyword arguments, due to PEP 3115.  However, the other use 
cases cannot.  Notably, any code that relies on in-class decorators or 
conditional class decorators (such as method decorators that add class 
decorators), will not be able to work.

However, I have an idea for a small modification to PEP 3115 that would 
re-enable support for both static and dynamic class decorators, and make it 
possible to implement an improved super() as well.

Suppose that we reserved a special name, '__decorators__', that would be 
contained in the mapping object returned by '__prepare__', and initialized 
to contain any static decorators defined outside the class, e.g., this code:

     @implements(IFoo)
     @otherdecorator
     class X:
         print __decorators__

would print a list equal to [implements(IFoo), otherdecorator].  The idea 
here is that following the execution of metaclass(name, bases, classdict, 
**kw), the __decorators__ list would be repeatedly popped to yield 
decorators to be invoked on the "finished" class.  In this way, code that 
needs dynamic access to the finished class can simply add objects to 
__decorators__.

As a result, we could then implement a super() enhancement of the form 
"super(__class__, self).methodname(args)", where "__class__" would be a 
compiler-defined variable (ala "__debug__").  If any function inside a 
class body uses "__class__", a preamble is added to the class body that 
defines an anonymous callback function that sets a closure variable to 
point to the class, and returns the class.  This anonymous callback 
function is then appended to __decorators__.

So, this approach could be used to enhance super() directly (using 
__class__ instead of a specific class), or as a behind-the-scenes part of 
the implementation of a more "sugary" syntax.  It would also continue to 
enable dynamic class decorators for other uses.

Thoughts?



More information about the Python-3000 mailing list