@decorator syntax is sugar, but for what exactly?

Bengt Richter bokr at oz.net
Sun Aug 8 01:50:47 CEST 2004

ISTM that
    def func(): pass

is syntactic sugar for creating a hidden list of functions. (Using '|' in place of '@'
doesn't change the picture much (except for people whose tools depend on '@' ;-)).

I.e., (not having the source or time to delve) the apparent semantics of the above
is something roughly like

    __funclist__ = []
    def func():pass
    while __funclist__: func = __funclist__.pop()(func)
    del __funclist__

Is this a special case of a more general idea? E.g., could it apply to
right after ANY next name is bound, in general, not just a name bound by def?

thus (untested)

    def censor(cls):
        cls.__repr__ = lambda self: '<CENSORED>'
        return cls
    class C(object): pass

could have the expected effect (after metaclass effects, if any, presumably, BTW)
(note that censor could instead e.g. wrap selected methods or add class variable data etc.,
though IIRC __metaclass__ can create some things that are read-only later)

This is still very narrowly defined by prefix context. Is this context also
a special case default of something more general? IOW the default choice for
namespace is the lexically enclosing one. What about, e.g., being able to specify
decoration in one place at the top of a module and decorate (in the same way, using
the same function list) all methods of a specified (by name) list of classes?

I.e., a more general control over what to do when what names are bound in what namespace
could be envisaged. This begins to feel like event-driven processing. Could @deco1 @deco2
be sugar for the special case (don't take this literally, just illustrating semantics ;-)

    when(event='next_binding', namespace='immediate', symbols='any', funclist=(deco1,deco2))
    def foo(): pass

of something general that could also include other and possibly repeated events like on completion
of an arg list for a particular function or method being called or any rebinding of particular
symbols in a specified namespace (not just the immediate one), e.g., for debugging or profiling etc.

Since I am copying this to python-dev, I'll re-ask whether @decorator has any peculiar
thread safety pitfalls that should be warned against, just in case.

Please take this as a probe into the intended semantics, not as a proposal for any particular
functionality ;-)

Bengt Richter

More information about the Python-list mailing list