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

Guido van Rossum guido at python.org
Tue May 1 02:38:25 CEST 2007

On 4/30/07, Phillip J. Eby <pje at telecommunity.com> wrote:
> At 03:54 PM 4/30/2007 -0700, Guido van Rossum wrote:
> >On 4/30/07, Phillip J. Eby <pje at telecommunity.com> wrote:
> >>At 12:17 PM 4/30/2007 -0700, Guido van Rossum wrote:
> >> >Assuming class decorators are added, can't you do all of this using a
> >> >custom metaclass?
> >>
> >>The only thing I need for the GF PEP is a way for a method decorator to get
> >>a callback after the class is created, so that overloading will work
> >>correctly in cases where overloaded methods are defined in a subclass.
> >
> >I still don't understand why you can't tell the users "for this to
> >work, you must use my special magic super-duper metaclass defined
> >*here*". Surely a sufficiently advanced metaclass can pull of this
> >kind of magic in its __init__ method? If not a metaclass, then a
> >super-duper decorator. Or what am I missing?
> Metaclasses don't mix well.  If the user already has a metaclass, they'll
> have to create a custom subclass, since Python doesn't do auto-combination
> of metaclasses (per the "Putting Metaclasses to Work" book).  This makes
> things messy, especially if the user doesn't *know* they're using a
> metaclass already (e.g., they got one by inheritance).
> For the specific use case I'm concerned about, it's like "super()" in that
> a function defined inside a class body needs to know what class it's
> in.  (Actually, it's the decorator that needs to know, and it ideally needs
> to know as soon as the class is defined, rather than waiting until a call
> occurs later.)
> As with "super()", this really has nothing to do with the class.  It would
> make about as much sense as having a metaclass or class decorator called
> ``SuperUser``; i.e., it would work, but it's just overhead for the user.
> So, if there ends up being a general way to access that "containing class"
> from a function decorator, or at least to get a callback once the class is
> defined, that's all I need for this use case that can't reasonably be
> handled by a normal metaclass.
> Note, too, that the such a hook would also allow you to make classes into
> ABCs through the presence of an @abstractmethod, without also having to
> inherit from Abstract or set an explicit metaclass.  (Unless of course you
> prefer to have the abstractness called out up-front...  but then that
> explicitness goes out the window as soon as you e.g. sublcass Sequence from
> Iterable.)
> >But I don't understand how a __metaclass__ hack can use a class decorator.
> The __metaclass__ hack is used in Python 2.x to dynamically *add* class
> decorators while the class suite is being executed, that will be called
> *after* the class is created.  A function decorator (think of your
> @abstractmethod, for example) would monkeypatch the metaclass so it gets a
> crack at class after it's created, without the user having to explicitly
> set up the metaclass (or merge any inherited metaclasses).

It sounds like you were accessing __metaclass__ via sys._getframe()
from within the decorator, right? That sounds fragile and should not
be the basis of anything proposed for inclusion into the standard
library in a PEP. Perhaps the GF PEP could propose a standard hook
that a class could define to be run after the class is constructed.
The hook could be acquired by regular inheritance.

I think it's entirely reasonable to require that, in order to use an
advanced feature *that is not yet supported by the core language*,
users need to enable the feature not just by importing a module and
using a decorator but also by something they need to do once per
class, like specifying a metaclass, a class decorator, or a magic base

Of course, once the core language adds built-in support for such a
feature, it becomes slightly less advanced, and it is reasonable to
expect that the special functionality be provided by object or type or
some other aspect of the standard class definition machinery (maybe
even a default decorator that's always invoked).

--Guido van Rossum (home page: http://www.python.org/~guido/)

More information about the Python-3000 mailing list