When I recently looked at Flask's view decorator, I suddenly remembered that I had learned the Python decorator.
Here's a good tutorial on how to write a decorator in Python (Nine steps to get started).
There is no separate recording of the decorator's writing format, which focuses on the workflow.
The first common adorner format is through the @ Syntax sugar, a simple way of writing, so that the process is not very clear.
In the case of an adorner without parameters:
def deco (func): Def _deco (): Print ("before MyFunc () called.") Func () print ("After MyFunc () called.") return _deco @decodef myfunc (): Print ("MyFunc () called.") MyFunc ()
Operation Result:
Before MyFunc () Called.myfunc () Called.after myfunc () Called.myfunc () called.
The function of this @ Grammar sugar is:
Def myfunc (): Print ("MyFunc () called.") MyFunc = Deco (MyFunc)
That is, now the MyFunc is no longer the one defined at the beginning, and becomes
Def _deco (): Print ("before MyFunc () called.") Func () print ("After MyFunc () called.")
This can be done by
Print myfunc.__name__
And more complex, the adorner with parameters, such as:
def deco (arg= "haha"): Def _deco (func): Def __deco (): Print ("before%s called [%s]."% (func.__name__, ARG), func () print ("after%s called [%s]."% (func.__name__, arg)) return __deco return _deco@deco () #注意有括号def myfunc (): Print ("MyFunc () called.") @deco ("Haha1") def myfunc1 (): Print ("MyFunc () called.") MyFunc () myfunc1 ()
The actual operation is that the decoration is first performed, that is, the function deco is called first
is equivalent to:
def _deco (func): Def __deco (): Print ("before%s called [%s]."% (func.__name__, Arg)) func () print ("after%s called [%s]."% (func.__name__, arg)) return __deco@d_deco# note without parentheses, first def myfunc (): Print ("MyFunc () Cal LED. ") @_deco# This also has no brackets, the second Def myfunc1 (): Print ("myfunc1 () called.") MyFunc () myfunc1 ()
The parameter arg is in the first place, using the default "haha" and the second using "HAHA1",
The more intuitive way to express it is:
def deco (arg= "haha"): Def _deco (func): Def __deco (): Print ("before%s called [%s]."% (func.__name__, ARG), func () print ("after%s called [%s]."% (func.__name__, arg)) return __deco return _decodef myfunc (): Print ("MyFunc () called.") def myfunc1 (): Print ("MyFunc () called.") MyFunc = Deco () (myfunc) myfunc1 = Deco ("Haha1") (MYFUNC1)
Then look at the use of wraps in standard library functools, such as the official website example:
From Functools import Wrapsdef my_decorator (f): @wraps (f) def wrapper (*args, **kwds): print ' calling decorate D function ' return F (*args, **kwds) return wrapper@my_decoratordef example (): "" "DocString" "" Print "Cal Led Example function ' Example () print Example.__name__print example.__doc__
Process is
Def my_decorator (f): Def wrapper (*args, **kwds): print ' calling decorated function ' return f (*args, **KWD s) wrapper.__name__ = f.__name__ wrapper.__doc__ = f.__doc__ return wrapperexample = My_decorator (example)
This preserves the original function name attribute and Doc,
The function wraps in the standard library can be understood as follows:
Def wraps (f): Def _f (*args,**kwargs): F (*args,**kwargs) _f.__name__ = f.__name _f.__doc__ = f.__doc__ Return _f
As can be seen in the wraps process above, if the direct use of wraps is simply F = f (in fact, it is not directly used), so it is generally shown as an example of the interior of an adorner function.
Note: The sample code comes from: Python decorator learning (nine-step primer) and Python standard library functools wraps
Python decorators and wraps in the standard library Functools