# This is a learning note for the Liaoche teacher Python tutorial
1. Overview
Adorners can help us add extra functionality to objects that already exist
An adorner is essentially a Python function that allows other functions to add extra functionality without any code changes, and the return value of the adorner is also a function object.
Adorners are often used in scenarios where there is a need for facets, such as inserting logs, performance testing, handling of things, caching, permission checking, and so on.
1.1. Add a row of logs for the now function
# define NOW function
def now ():
Print (' 2018-5-8 ')
# Edit Decorator
def log (func): # Accept the function of the name
def wrapper (*args,**kw): # receive parameters for incoming functions
print (' The function name is%s (): '% func.__name__) # Print the __name__ property of the function , note that __name__ is two _ ( Underline )
return func (*ARGS,**KW) # returns this function
Return wrapper
# Add decorator to the NOW function
@log
def now ():
Print (' 2018-5-8 ')
Placing the @log at the definition of the now () function is equivalent to executing the now=log. The procedure is "Wapper=log (now), Weapper returns now ()"
Since log () is a decorator that returns a function, the original now () function still exists, but the current variable with the same name currently points to the new function, and then the new function will be executed , i.e. the log () The wrapper () function returned in the function.
1.2, three-layer nested decorator
If the decorator itself needs to pass in parameters, it is necessary to write a higher-order function that returns decorator. For example, to customize the text of a log
def log (text):
def decorator (func):
def wrapper (*args, **kw):
Print ('%s%s (): '% (text, func.__name__))
return func (*args, **kw)
Return wrapper
return decorator
# Added to the now () function
@log (' Execute ')
def now ():
Print (' 2015-3-25 ')
# effect
>>> Now ()
Execute Now ():
2015-3-25
Three-layer nested execution effect: now = log (' Execute ') (now)
1.3. Property copy of primitive function
As can be seen from the above example, the now () function is ultimately returned by the wrapper function. The __name__ property of the Now () function has changed to ' wrapper '
>>> now.__name__
' Wrapper '
But our intention is only to add extra functionality to the now () function, and not to change its own properties, then we need to copy the properties of the () function to the wrapper () function
There's no need to write code like wrapper.__name__ = func.__name__, and Python's built-in functools.wraps is doing it.
functools.wraps:wraps itself is also an adorner, which can copy the meta-information of the original function into the adorner function . This allows the adorner function to have the same meta-information as the original function
# By the way, copy the property's decorator
Import Functools
def log (func):
@functools. Wraps (func) # This adorner is always above the wrapper function
def wrapper (*args, **kw):
Print (' Call%s (): '% func.__name__)
return func (*args, **kw)
Return wrapper
2. Example
1, please design a decorator, it can be used for any function, and print the function execution time:
#-*-Coding:utf-8-*-
Import time, Functools
def metric (FN):
@functools. Wraps (FN) # Copy the original function information to wrapper
def wrapper (*args, **kw):
Begin=time.time ()
Res=fn (*args, **kw) # Assign The return value of the FN function to res
End=time.time ()
print ("%s executed in%s MS"% (fn.__name__, (End-start) *1000)) # print Execution time Ms
return res
Return wrapper
2, before and after the execution of the function to print marks
def log (func):
def call (*ARGS,**KW):
Print (' Begin call ')
Out=func (*args,**kw) # The key is to assign the return value of a function to a variable, and the last return variable
Print (' End call ')
Return out
Return call
Python Learning note __4.4 decorator (add extra features)