I. Preface
Decorator: the essence is the function, the function is to add additional functionality to other functions
Principles:
- 1, do not modify the source code of the modified function
- 2. Do not modify the way the modified function is called
Decorators = higher-order functions + function nesting + closures
II. Higher-order functions
Higher-order function definitions:
- 1, the function receives the parameters of a function
- 2. The return value of a function is a function name
- 3. Satisfying any of the above conditions can be called a higher order function
The test function is a higher-order function that takes a foo as an argument
import time def foo(): (3) print("sleep 3s") def test(func): start_time = () func() stop_time = () print("The runtime of the function is: %s" % (stop_time - start_time)) test(foo)
timer is a higher-order function that returns a value of the function
import time def foo(): (3) print("sleep 3s") def timer(func): start_time = () func() stop_time = () print("execution time{}".format(stop_time - start_time)) return func foo = timer(foo) foo() # Result: one more run
Third, function nesting
Defining a function inside a function leaves the scope and lifetime of the variable unchanged.
def father(name): print("father name: %s" % name) def son(): print("son name: %s" % name) son() father("xu1") # Results: # father name: xu1 # son name: xu1
IV. Decorators
Implement a function that calculates the execution time of a function as a decorator, which is used to calculate the execution time of the decorated function and print it
import time def timer(func): # Implement a function that calculates the execution time of a function as a decorator to calculate the execution time of the decorated function and hit the def wrapper(): start_time = () func() stop_time = () print("Runtime: %s" % (stop_time - start_time)) return wrapper # def test(): # Equivalent implementation without decorator # (3) # print("test sleep 3s") # # test = timer(test) # returns the address of the wrapper # test() # The execution is wrapper @timer def test(): # Decorator implementation (3) print("test sleep 3s") test() # The execution is wrapper # Results: # test sleep 3s # Running time: 3.000915050506592
4.1 Decorated methods with return values
import time def timer(func): def wrapper(): start_time = () res = func() # Execute the decorated method stop_time = () print("Runtime: %s" % (stop_time - start_time)) return res # Accepts the return value of the method being called and returns the return wrapper @timer def test(): (3) print("test sleep 3s") return "test return ok" print(test()) # The execution is wrapper # Results: # test sleep 3s # Running time: 3.0002923011779785 # test return ok
4.2 Decorated methods with parameters
import time def timer(func): """ *args: packs non-keyword arguments passed by the modified method into a tuple args **kwargs: packs keyword arguments passed by the modified method into a dictionary kwargs """ def wrapper(*args, **kwargs): start_time = () res = func(*args, **kwargs) # *args disassembles tuples and passes them to the modified function in order; **kwargs: disassembles dictionaries stop_time = () print("Runtime: %s" % (stop_time - start_time)) return res return wrapper @timer # Add a decorator to the test method that calculates the execution time. def test(name, age): (3) print("name = {}, age = {}".format(name, age)) return "test return ok" # Call the method decorated by the decorator print(test("xu", 100)) # The execution is wrapper # Results: # name = xu, age = 100 # Running time: 3.000420331954956 # test return ok
4.3 Validation Function Decorator
If the index(), home(), and shopping_car() methods all need to be logged in to access them (without inputting the corresponding contents when they are inaccessible), then under normal circumstances you only need to log in once, and then you don't need to log in again to access the other methods later on.
You can verify whether the user is logged in through the @auth_fun decorator, if not let the user enter the account password, the user account password is correct to record the current logged in user, other methods do not need to log in again.
# User list user_list = [ {'name': 'xu1', 'passwd': '123'}, {'name': 'xu2', 'passwd': '123'}, {'name': 'xu3', 'passwd': '123'}, {'name': 'xu4', 'passwd': '123'}, ] # Currently logged in user current_dic = {"username": None, "login": False} # Decorator to verify that the user is logged in # If the user is not logged in, let the user enter the account password and record the user's status if the verification passes. def auth_fun(func): def wrapper(*args, **kwargs): if current_dic["username"] and current_dic['login']: res = func(*args, **kwargs) return res username = input("Please enter username:") pw = input("Please enter the password:") for u in user_list: if u["name"] == username and u["passwd"] == pw: current_dic["username"] = username current_dic["login"] = True res = func(*args, **kwargs) return res else: print("The user is not registered!") return wrapper @auth_fun def index(): print("this is index") @auth_fun def home(): print("this is home page") @auth_fun def shopping_car(): print("this is shopping car") index() # Enter user password home() # index is already logged in, there is no need to enter shopping_car() # index is already logged in, there is no need to enter # Results: # Please enter username:xu1 # Please enter password:123 # this is index # this is home page # this is shopping car
4.4 Validation Function Decorator - with Parameters
The simplest operation of a decorator with parameters is the ability to differentiate between the functions being decorated.
# User list user_list = [ {'name': 'xu1', 'passwd': '123'}, {'name': 'xu2', 'passwd': '123'}, {'name': 'xu3', 'passwd': '123'}, {'name': 'xu4', 'passwd': '123'}, ] # Currently logged in user current_dic = {"username": None, "login": False} """ take note of:Decorators with parameters will nest one more layer of functions than decorators without parameters(More.auth) The call is made by @auth(auth_type="type1"), come (or go) back auth_fun, in other words @auth(auth_type="type1")equivalent to @auth_fun still auth_fun 函数所在的嵌套作用域More.一个 auth_type variable """ def auth(auth_type="type1"): def auth_fun(func): def wrapper(*args, **kwargs): if auth_type == "type1": if current_dic["username"] and current_dic['login']: res = func(*args, **kwargs) return res username = input("Please enter username:") pw = input("Please enter the password:") for u in user_list: if u["name"] == username and u["passwd"] == pw: current_dic["username"] = username current_dic["login"] = True res = func(*args, **kwargs) return res else: print("The user is not registered!") elif auth_type == "type2": print("Direct login without authorization: type = {}".format(auth_type)) res = func(*args, **kwargs) return res else: print("Other types are not realized.") return wrapper return auth_fun """ auth_fun = @auth(auth_type="type1") auth_fun The nesting where it is located is the same as the nesting where there will be a auth_type variant and then through @auth()methodologiescome (or go) back的boyfriendannotate index,equivalent to @auth_fun annotateindex methodologies,end result wrapper boyfriend """ @auth(auth_type="type1") def index(): print("this is index") @auth(auth_type="type2") def home(): print("this is home page") @auth(auth_type="type3") def shopping_car(): print("this is shopping car") home() # Note: auth_type="type2", this method can be executed directly without login. index() # Note: auth_type="type1", requires login shopping_car() # Note: auth_type="type3", not processed # Results: # Login without authorization: type = type2 # this is home page # Please enter username:xu1 # Please enter password:123 # this is index # Other types not implemented
to this article on the basis of python decorator detailed article is introduced to this, more related python decorator content please search for my previous articles or continue to browse the following related articles I hope you will support me in the future more!