Decorator Design Techniques
Composite design
The common mathematical notation for a composite function looks as follows:
fgxfgx ()()= ()
The idea is that we can define a new function, fgx (), that combines two other
functions, fy()and gx().
Python's multiple-line definition of the form is as follows:
@f
def g(x):
something
This is vaguely equivalent to fgx (). The equivalence isn't very precise because
the @f decorator isn't the same as the mathematical abstraction of composing fy()
and gx(). For the purposes of discussing function composition, we'll ignore the
implementation disconnect between the abstraction of fy() and the @f decorator.
Because decorators wrap another function, Python offers a slightly more generalized
composition. We can think of Python design as follows:
wgwxwgwxβαi i ()= βα()()()
A decorator applied to some application function, gx(), will include a wrapper
function. One portion of the wrapper, wxα(), applies before the wrapped function
and the other portion, wxβ(), applies after the wrapped function.
The Wrapper() function often looks as follows:
@wraps(argument_function)
def something_wrapper(*args, **kw):
The "before" part, w_α, applied to *args or **kw
result= argument_function(*args, **kw)
the "after" part, w_β, applied to the result
Details will vary, and vary widely. There are many clever things that can be done
within this general framework.