Wednesday, August 29, 2007

Use case for decorators

Intro

Decorators were introduced in Python 2.4 but remain a somewhat obscure feature of the language. A decorator essentially is a function that you apply to another function, replacing it with the return value of the decorator function:
def d(f):
...

@d
def g():
...
This is equivalent to:
def d(f):
...

def g():
...

g = d(g)
More background here.

The use case

As part of my research project, I’m testing several ways to explain side effects of drugs. So I made a class that loads all the relevant data into memory and that contains methods to fit the data. (I thought about creating subclasses replacing the “fit” method of the base class. However, the data that’s being loaded into memory is the same for all instances of the subclasses, so I don’t want to reload it every time. Thus, I put multiple methods into the base class.)
At first, I used introspection to identify the relevant functions by name (using dir) and then calling them. This worked fine, but it doesn’t make it particularly easy to disable some of the functions. Enter decorators: I wrote a decorator that takes a function, puts it into a list (which is a global variable) and returns the function unchanged. To call every fitting function, I can just iterate over the list. If I want to disable a function, I just comment out one line. Yay!



Another neat trick is that the docstring of each function is accessible as an attribute, so that each fit comes together with a description.

Tuesday, August 28, 2007

Running in circles

You know you're looking for an obscure topic when your own entry in CiteULike comes up on the second page or so of the Google results.

Luckily, I saw my name in the URL and so I didn't get frightened by a Woozle.