Defining Complex Decorators
A decorator transforms an argument function definition into a
result function definition. In addition to a function, we can also
provide argument values to a decorator. These more complex decorators
involve a two-step dance that creates an intermediate function as well
as the final result function.
The first step evaluates the abstract decorator to create a
concrete decorator. The second step applies the concrete decorator to
the argument function. This second step is what a simple decorator
does.
Assume we have some qualified decorator, for example @debug(
flag ), where flag can be True to enable
debugging and False to disable debugging. Assume we
provide the following function definition.
debugOption= True
class MyClass( object ):
@debug( debugOption )
def someMethod( self, args ):
real work
Here's what happens when Python creates the definition of the
someMethod function.
-
Define the argument function,
someMethod.
-
Evaluate the abstract decorator debug( debugOption
) to create a concrete decorator based on the argument
value.
-
Apply the concrete decorator the the argument function,
someMethod.
-
The result of the concrete decorator is the result function,
which is given the name someMethod.
Here's an example of one of these more complex decorators. Note
that these complex decorators work by creating and return a concrete
decorators. Python then applies the concrete decorators to the argument
function; this does the work of transforming the argument function to
the result function.
Example 26.4. debug.py
def debug( theSetting ):
def concreteDescriptor( aFunc ):
if theSetting:
def debugFunc( *args, **kw ):
print "enter", aFunc.__name__
return aFunc( *args, **kw )
debugFunc.__name__= aFunc.__name__
debugFunc.__doc__= aFunc.__doc__
return debugFunc
else:
return aFunc
return concreteDescriptor
|
This is the concrete decorators, which is created from the
argument, theSetting.
|
|
If theSetting is
True, the concrete decorator will create the
result function named debugFunc, which
prints a message and then uses the argument function.
|
|
If theSetting is
False, the concrete descriptor will simply
return the argument function without any overhead.
|