Michele Simionato wrote a sweet module ( called decorators )that dramatically simplifies the usage of decorators in Python.
The example below is based on one of the samples Michele provides and should help illustrate how much simpler it is to create decorators
Suppose you have a function called foo() that prints “Hello World” and that it’s used frequently in your codebase
def foo() : print “Hello World”
Imagine you are investigating some anomalous behavior and you’d like to emit some text to the console knowing when foo has been called and then when it exits. This is a very common scenario when debugging or in applications that do logging for a complex installation/configuration.
The Brute-force method without decorators
The brute-force approach is to modify foo()
def foo() : print "ENTER foo" print “Hello World” print "EXIT Foo"
This works but it has some issues
- you had to modify the function
- the modification must be reimplemented for other functions
- notice that it if you change the name of the function for example to “bar” you’ll have to change code that prints the name of the function
Using decorators with the decorator module
Now let’s try with the decorator module
There are two steps:
- use @decorator to create a decorator in this case called @tracing
- use the @tracing decorator on a function you want to trace
from decorator import * @decorator def tracing (f, *args, **kw) : print "ENTER", f.func_name retval = f(*args,**kw) print "EXIT", f.func_name return retval @tracing def foo() : print "Hello World"
And now what happens when we call foo()?
>>> foo() ENTER foo Hello World EXIT foo >>>
The tracing() method just wraps a function call with with print statements
- The function we are tracing didn’t need to be modified
- we can reuse the tracing code
- The tracing will use the correct function name.
Recommendation: Try it
This post only scratched the surface; you can find out more here: http://www.phyast.pitt.edu/~micheles/python/documentation.html