[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:
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
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.
More information about the Python-3000