Radical: listing decorators compared to atexit function registration

Bengt Richter bokr at oz.net
Wed Aug 25 22:26:26 CEST 2004

Still looking for a unifying concept ;-)

It struck me that

    def foo():pass

uses '@' to register at-next-name-binding processing in a way similar to atexit's
registering of processing to happen at ('@' ;-) exit.

IOW, it is setting up processing for an event (synchronous in this case)
that is expected to happen in the future.

I like that meaning of '@' -- i.e., @event_handler_defining_expression seems like
a nice general reading of an 'at'-symbol.

In the case of function decoration, the event is implicitly the completion of the
execution of next-in-code-sequence function definition, intercepting
just before name-binding. And a chain of interceptions works in order.

In the case of current decorators, deco1 etc must be expressions resulting in
functions. By default, the functions are hooked into a chain of at-next-name-binding
processing that gets triggered by the def name binding. This is the current use case.

However, the broader concept is for @expression to cause registration of a generalized
event handler into an event recognition/handling mechanism. The concept can be embellished
with one-shot vs repeated and with or without timeout, multiple events, etc., but leave
that for later, so long as the door is not closed to it.

If @expression evaluating to a function defaults to a certain meaning, it should be
possible to spell it out using a compatible general and full spelling. OTTOMH ISTM
that the natural alternative to returning a function or ordinary callable would be
to return an object that the infrastructure would recognize and register into the
appropriate alternative event-handling place.

One way would be if the object were marked in a similar way that an object gets
marked as a descriptor (which happens with a __get__ method etc). Perhaps __handler__ ?
Thus you could write a class with a __handler__ method and instantiate it with info
re what event to recognize and other particulars. Then decorator syntax spelled out
might look (in concept, this is not a design spec ;-) like:

    @my_next_binding_handler(func=deco1, event='before_next_local_binding')
    @my_next_binding_handler(func=deco2, event='before_next_local_binding')
    def foo():pass

Note that you could potentially define object attribute access events and have another way
to define properties, if you passed info to your handler constructor specifying name and
namespace. Obviously the infrastructure would have to grow some event-handling and 
relevant registration etc magic.

This is essentially a push to start thinking about bringing generalized event-driven
programming nicely into python. I'm suggesting that decorators can be seen as special
one-shot event handlers for a local binding event. A GUI is obviously a source of many
user action events, and a way to say @mouseover('this','that') to instantiate and
register some code might be neat. Ditto for i/o related events. This brings in thread
issues though, and event queuing etc. But that can be deferred. We can just deal with
synchronous events for the time being. Hm... recoverable exceptions anyone ;-)

OTOH, this may all just be a symptom of attempted personal stress escape ;-)

Bengt Richter

More information about the Python-list mailing list