A decorator is a function which accepts a function and returns a
new function. Consequently, most decorators include a function
definition and a
statement. A common
alternative is to include a class definition as well as a
statement. If a class definition is used, it
must define a callable object by including a definition for the
There are two kinds of decorators, decorators without arguments
and decorators with arguments. In the first case, the operation of the
decorator is very simple. In the second case, the definition of the
decorator is rather obscure. We'll look at the simple decorators first.
We'll defer more complex decorators to the next section.
A simple decorator has the following outline:
def myDecorator( argumentFunction ):
def resultFunction( *args, **keywords ):
including a call to argumentFunction
In some cases, we may replace the result function definition with
a result class definition to create a callable class.
Here's a simple decorator that we can use for debugging. This will
log function entry, exit and exceptions.
Example 26.2. trace.py
def trace( aFunc ):
"""Trace entry, exit and exceptions."""
def loggedFunc( *args, **kw ):
print "enter", aFunc.__name__
result= aFunc( *args, **kw )
except Exception, e:
print "exception", aFunc.__name__, e
print "exit", aFunc.__name__
The result function,
built when the decorator executes. This creates a fresh, new
function for each use of the decorator.
Within the result function, we evaluate the original
function. Note that we simply pass the argument values from the
evaluation of the result function to the original
We move the original function's docstring and name to the
result function. This assures us that the result function looks
like the original function.
Here's a class which uses our
Example 26.3. trace_user.py
class MyClass( object ):
def __init__( self, someValue ):
"""Create a MyClass instance."""
def doSomething( self, anotherValue ):
"""Update a value."""
self.value += anotherValue
Our class definition includes two traced function definitions.
Here's an example of using this class with the traced functions. When we
evaulate one of the traced methods it logs the entry and exit events for
us. Additionally, our decorated function usees the original method
function of the class to do the real work.
mc= MyClass( 23 )
mc.doSomething( 15 )