I had some trouble understanding decorators, especially on how to get decorators to execute in the order I wanted. That is, do_something() before the decorated function, or after the decorated function.
Jon Rosebaugh gave me this quick sample to explain how to get my decorator to execute in the desired order. In this case, he did a print statement instead of do_something(), but it's still pretty straight forward.
from decorator import decorator @decorator def pre_call(f, *a, **kw): print "I'm using the internet!" return f(*a, **kw) @decorator def post_call(f, *a, **kw): result = f(*a, **kw) print "I'm using the internet!" return result def f1(): print "Hello World" f2 = pre_call(f1) f3 = post_call(f1) print "calling f1" f1() print "calling f2" f2() print "calling f3" f3()
If you just call f1(), of course you'll see "Hello World". No surprise there.
Calling f2() is a bit different though, it wraps the f1 function in pre_call - pre_call(f1)
@pre_call def f1(): print "Hello World"
The result you'll get with this is the following:
I'm using the internet! Hello World
Inversely, if you call f3(), which wraps the f1 function in post_call, the original function, f1 gets executed to begin with in the line result = f(*a, **kw), and is returned after the decorator's print statement is fired. The result is of course this:
Hello World I'm using the internet!
In Pylons, pre-call decorators are useful for intercepting controller requests and doing things like authentication. Post-call decorators on the other hand are more useful for transforming data, just as the pylons.decorators.jsonify does in taking the output of a controller, and turning it into a JSON string. Another post-call decorator might turn all your output text into pig-latin, or if you're really anal, censor those seven deadly words.
June 25th, 2008 at 6:42 am
I notice that you’re still using the decorator module. I was doing this myself until I discovered recently that you can use the “wraps” function from the “functools” module in the standard library. Its semantics are a little different, but it accomplishes exactly the same thing.
Of course, you may just prefer how the decorator module makes your code look.