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

Eric Snow ericsnowcurrently at gmail.com
Mon Apr 6 18:12:07 CEST 2015


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

Here's another approach that would help.  Support a mechanism for
inheriting class decorators.  Classes would have an attribute like
__subclass_decorators__ that would hold a tuple of all the inherited
decorators.  They would be applied, in order, in __build_class__
before any explicit decorators are.

One way to accomplish this is with a meta-decorator, e.g.
"classutil.inherited_decorator".  You would decorate a class decorator
with it:

def inherited_decorator(deco):
    def new_deco(cls):
        cls = deco(cls)
        try:
            inherited = cls.__subclass_decorators__
        except AttributeError:
            cls.__subclass_decorators__ = (deco,)
        else:
            cls.__subclass_decorators__ = inherited + (deco,)
        return cls

@inherited_decorator
def register(cls):
    registry.add(cls)
    return cls

@register
class X:
    ...

The downside to the meta-decorator is that is isn't apparent when the
class decorator is used that it will be inherited.  It could also be
used directly to make it more apparent:

def register(cls):
    registry.add(cls)
    return cls

@inherited(register)
class X:
    ...

However, that doesn't read well.  Syntax would be better, but is a
harder sell and a little grittier:

def register(cls):
    registry.add(cls)
    return cls

@@register
class X:

-eric


More information about the Python-Dev mailing list