[Python-Dev] PEP 487 vs 422 (dynamic class decoration)

Martin Teichmann lkb.teichmann at gmail.com
Fri Apr 3 14:44:18 CEST 2015


> When I first wrote PEP 422 I was of the view that "Python 2 allows
> class definition postprocessing injection, we should allow it in
> Python 3 as well". I've since changed my view to "Having to declare
> post-processing of a class definition up front as a decorator, base
> class or metaclass is a good thing for readability, as otherwise
> there's nothing obvious when reading a class definition that tells you
> whether or not postprocessing may happen, so you have to assume its
> possible for *every* class definition".

Nick, I couldn't agree more with you, yet I think PJ actually brought
up a very interesting point. Post-processing is a very common thing
these days, and has been re-written so many times that I think it is
about time that something like it should be in the standard library.

I'm less thinking about decorated methods, more about descriptors.
They always have the problem that they don't know which attribute they
belong to, so every author of a framework that defines descriptors
writes a metaclass which goes through all the descriptors and tells
them their attribute name.

I propose to have some metaclass in the standard library that does
that. I think it would fit nicely in my metaclass module proposed in
PEP 487.

It would basically do the following:

class Metaclass(type):
    def __init__(self, name, bases, dict):
        super().__init__(name, bases, dict)
        for k, v in dict.items():
            if hasattr(v, "__post_process__"):
                v.__post_process__(k, self)

So each descriptor could define a __post_process__ hook that tells
it the attribute name and also the class it belongs to. This would for
sure also work for decorated methods.

This should mature on PyPI, then introduced into the standard library,
and if demand is really that high, maybe even be introduced into
type.__init__. It should be noted that this can also be easily written
as a PEP 487 class using __subclass_init__, I just used the classical
metaclass notion as I guess people are more used to that.

This proposal can actually be seen as an extension to the __class__
and super() mechanism of normal methods: methods currently have the
priviledge to know which classes they are defined in, while descriptors
don't. So we could unify all this by giving functions a __post_process__
method which sets the __class__ in the function body. This is about the
same as what happened when functions got a __get__ method to turn
them into object methods.

While this all is in the making, PJ could monkey-patch __build_class__
to do the steps described above, until it gets accepted into cpython.
So I pose the question to PJ: would such an approach solve the
problems you have?

Greetings

Martin


More information about the Python-Dev mailing list