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