Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Defining Decorators

A decorator is a function which accepts a function and returns a new function. Consequently, most decorators include a function definition and a return statement. A common alternative is to include a class definition as well as a return statement. If a class definition is used, it must define a callable object by including a definition for the __call__ method.

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 ):
       
enhanced processing

       
including a call to argumentFunction

   resultFunction.__doc__= argumentFunction.__doc__
   return resultFunction

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__
        try:
            result= aFunc( *args, **kw )
        except Exception, e:
            print "exception", aFunc.__name__, e
            raise
        print "exit", aFunc.__name__
        return result
    loggedFunc.__name__= aFunc.__name__
    loggedFunc.__doc__= aFunc.__doc__
    return loggedFunc
1

The result function, loggedFunc, is built when the decorator executes. This creates a fresh, new function for each use of the decorator.

2

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 function.

3

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 @trace decorator.

Example 26.3. trace_user.py

class MyClass( object ):
    @trace
    def __init__( self, someValue ):
        """Create a MyClass instance."""
        self.value= someValue
    @trace
    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 )

enter __init__
exit __init__

>>> 
mc.doSomething( 15 )

enter doSomething
exit doSomething

>>> 
mc.value

38

 
 
  Published under the terms of the Open Publication License Design by Interspire