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

Eric Snow ericsnowcurrently at gmail.com
Sun Apr 5 00:00:55 CEST 2015


On Fri, Apr 3, 2015 at 6:44 AM, Martin Teichmann
<lkb.teichmann at gmail.com> wrote:
>> 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.

I've felt for a long time that it would be helpful in some situations
to have a reverse descriptor protocol.  What you are describing it a
strict subset of that concept (which is fine).  It may be worth
considering a method name that would also be used for that more
generic reverse descriptor, rather than having 2 names for the same
thing.  Even if such a protocol never materializes, the name borrowed
here would still be informative.

-eric


More information about the Python-Dev mailing list