I've been experimenting with Python recently for a few different reasons:
- It's fun to learn new things
- I'm planning to build a site for a friend on top of Django and Wagtail
- I have some ideas for Kodi Addons
I had the need to implement an observer pattern for decoupled publish/subscribe messaging between independent Python modules. C# has this built in to the language with events. I found this Stack Overflow post where user Jason Orendorff's answer provided the following excellent decorator:
This is difficult at first to understand as a Python noob, but once you get it you appreciate the simplicity and the power the language has. Starting at the bottom, the boundevent
class stores the event handlers and iterates over them when the function is invoked (i.e., the event is 'raised'). The event
decorator exposes the boundevent
(that is stored on the object instance) for a given event (which is really just a method) when it is accessed via the '.' notation.
This may seem unimpressive. After all, C# has this event syntax baked in. You can even override the the event accessors if need be. But the thing is, the language actually has to implement those features, just like with automatic properties (remember when they didn't exist?). In this case, we're creating this 'language feature' for events without actually extending the language. All we need is the syntactic sugar provided by '@'
combined with the late-binding characteristics of Python to create these events. @property
does the same thing; it just happens to be built-in.
Here is my example of its usage:
This is plain awesome, and it just works. A couple of subtle things I like about this are
- You can actually use any arguments you want on the event definition, which can be useful for documentation. There is nothing to enforce method signature. It does need one argument to correspond with
self
, but it can be named anything, as is the case with this example. - Completely separate from anything event-related, the doc comment actually does translate to code, which eliminates need for the
pass
keyword (I think).
Comments