I often talk about the Python advanced decorator and the python advanced decorator.
Functions are also objects
To understand the Python modifier, you must first understand that in Python, a function is also an object. Therefore, you can regard the function name when defining a function as a reference to a function object. Since it is a reference, you can assign a function to a variable, or pass or return a function as a parameter. You can also define functions in the function body.
Decorator nature
You can write a pure function example to restore what the decorator is doing.
def decorator(func): def wrap(): print("Doing someting before executing func()") func() print("Doing someting after executing func()") return wrapdef fun_test(): print("func")fun_test = decorator(fun_test)fun_test()# Output:# Doing someting before executing func()# func# Doing someting after executing func()
The reference of the function pointed to by fun_test is passed to the decorator () function.
The decorator () function defines the wrap () subfunction, which calls the fun_test () function passed in through func reference, some other things were done before and after the function was called.
The decorator () function returns the internally defined wrap () function reference.
Fun_test receives the function reference returned by decorator () and points to a new function object.
Use fun_test () to call the new function to execute the wrap () function, thus completing the decoration before and after the fun_test () function.
Decorator used in Python
In Python, you can use the @ symbol to conveniently use the decorator function.
def decorator(func): def wrap(): print("Doing someting before executing func()") func() print("Doing someting after executing func()") return wrap@decoratordef fun_test(): print("func")fun_test()# Output:# Doing someting before executing func()# func# Doing someting after executing func()
The decoration function has been implemented, but the following code is executed:
print(fun_test.__name__)# Output:# wrap
Fun_test. _ name _ has been changed to wrap. This is because the wrap () function has rewritten our function name and annotation document. You can solve this problem through functools. wraps. Wraps is decorated by a function, and supports copying function names, commenting documents, parameter lists, and other functions. This allows us to access the attributes of the function before decoration in the decorator.
More standardized writing:
from functools import wrapsdef decorator(func): @wraps(func) def wrap(): print("Doing someting before executing func()") func() print("Doing someting after executing func()") return wrap@decoratordef fun_test(): print("func")fun_test()print(fun_test.__name__)# Output:# Doing someting before executing func()# func# Doing someting after executing func()# fun_test
Decorator with Parameters
By returning a function of the wrap function, you can simulate the wraps decorator and construct a decorator with parameters.
from functools import wrapsdef loginfo(info='info1'): def loginfo_decorator(func): @wraps(func) def wrap_func(*args, **kwargs): print(func.__name__ + ' was called') print('info: %s' % info) return func(*args, **kwargs) return wrap_func return loginfo_decorator @loginfo()def func1(): pass func1()# Output:# func1 was called# info: info1@loginfo(info='info2')def func2(): passfunc2()# Output:# func2 was called# info: info2
Decorations
By writing classes, you can also implement the decorator and make the decorator more practical in inheritance and other object-oriented features.
First, write a base class for the decorator:
From functools import wrapsclass loginfo: def _ init _ (self, info = 'info1'): self.info = info def _ call _ (self, func ): @ wrap def wrap_func (* args, ** kwargs): print (func. _ name _ + 'was called') print ('info: % s' % self.info) self. after () # Call The after method. You can implement return func (* args, ** kwargs) return wrap_func def after (self) in the subclass ): pass @ loginfo (info = 'info2 ') def func1 (): pass # Output: # func1 was called # info: info1
Inherit the loginfo class to extend the functions of the decorator:
class loginfo_after(loginfo): def __init__(self, info2='info2', *args, **kwargs): self.info2 = info2 super(loginfo_after, self).__init__(*args, **kwargs) def after(self): print('after: %s' % self.info2)@loginfo_after()def func2(): passfunc2() # Output:# func2 was called# info: info1# after: info2
The above is a common example of the Python advanced modifier, which is all the content shared by the editor. I hope to give you a reference and support for the house of friends.