Skip to main content

C#-like Events in Python

I've been experimenting with Python recently for a few different reasons:

  1. It's fun to learn new things
  2. I'm planning to build a site for a friend on top of Django and Wagtail
  3. 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

  1. 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.
  2. Completely separate from anything event-related, the doc comment actually does translate to code, which eliminates need for the pass keyword (I think).

Comments

Popular posts from this blog

Who I'm Is

I am a junior .NET developer currently working in Chicago, IL. I am starting this blog in order to enhance my knowledge of programming subject matter. Hopefully, someone else will be helped along the way. This first post will probably be edited soon...

Stubbing Static Methods with PostSharp

TypeMock uses the Profiler API to allow mocking, stubbing, etc. of classes used by code under test. It has the ability to handle sealed classes, static classes, non-virtual methods, and other troublesome-yet-oft-encountered scenarios in the world of unit testing. Other frameworks rely on proxies to intercept method calls, limiting them to be able to only fake virtual, abstract, and interface members. They also rely on dependecy injection to place the proxies as the concrete implementation of calls to the abstracted interface members. Anyone working with a legacy codebase is bound to run into static method calls (especially in the data access layer), dependencies on concrete types with non-virtual methods, and sealed class dependencies (HttpContext anyone?). The only way to unit test this without refactoring is with TypeMock. I've never used TypeMock, and I'm sure it's a great product, but it's not free. I decided to spike some code to see if I could solve the prob...

Strongly-Typed Property Constraints in Rhino Mocks

UPDATE: As I suspected, this functionality was right in front of my face – it’s called PredicateConstraint in Rhino Mocks. I also realize that I managed to completely ignore the existence of Predicate<T> in the framework, and write my own predicate delegate. Hey, I was on a roll. Rhino Mocks has a PropertyConstraint class that allows you to check the values on properties of objects passed into the method as part of the verification for that method being called. Unfortunately, the name of the property is specified as a string, which means the benefits of strong-typing that Rhino Mocks is normally so good at preserving are lost. Here’s an example (using Rhino Mocks 3.3 and .NET 2.0): [Test] public void Main_Form_Should_Show_Start_Panel_On_Load() { MockRepository mockRepository = new MockRepository(); IMainFormView mockView = mockRepository.DynamicMock<IMainFormView>(); IEventRaiser loadEventRaiser = GetEventRaiserFor(delegate { mockView.Load += null; });...