1. The essence of ornament
The decorator is essentially a closure function, which allows other functions to add additional functions without any code changes. The return value of the decorator is also a function.
-
Closure function
1) It must be a nested function, that is, an inner function is defined in the outer function;
2) The inner function references variables in the scope of the outer function (Note: non global);
3) The return value of the outer function is the reference of the inner function;
4) Check whether the function is a closure function: function;
-
function
1) What is a function: a well-organized, reusable code segment used to implement a single or associated function;
2) The advantages of function: function can improve the modularity of application and the reuse rate of code;
3) Definition of function: use def keyword;
def func(): print("Hello, World!")
4) Function parameters: there are different concepts of function parameters according to function definition and call;
- When defining: position parameter, default parameter and indefinite length parameter;
def func(a, b=0, *args, **kwargs): print(f"Location parameters:{a}") print(f"Default parameters:{b}") print(f"Indefinite length parameter: tuple{args},Dictionaries{kwargs}")
- When calling: required parameter (must be passed), keyword parameter (can be passed but not passed), indefinite length parameter (can be passed but not passed);
func("Hello") # "Hello" >> a func("Hello", b=1) # "Hello" >> a, 1 >> b func("Hello", 2) # "Hello" >> a, 2 >> b func("Hello", 2, 3, c="World") # "Hello" >> a, 2 >> b, 3 >> *args, c="World" >> **kwargs
5) Anonymous function: using the lambda keyword is only an expression, not a code block, with limited logic;
add = lambda a, b: a + b
6) Variable scope: LEGB;
- 50: L ocal, Local scope;
- E: Closing, in a function other than a closure function;
- G: Global, global scope;
- B: Built in, Built-in scope;
7) Some concepts about function;
- Function is variable: function can be used as parameter or return value;
- Higher order function: a function that takes a function as a parameter or return value, and has built-in functions map(), filter(), and reduce() in the functools package;
- Nested function: define function in function;
- Life cycle of variables in nested functions: normally, when a function ends running, all local objects of the function will be recycled to free memory. But closures are a special case. In the closure, if the temporary variable in the scope of the external function is called by the internal function at the end of the external function, the external function will bind the variable to the internal function, and then end;
2. Decorator should meet the conditions
- Add new functions to the decorated function;
- The code of the decorated function cannot be changed;
- The call mode of the decorated function cannot be changed;
3. Application scene of decorator
- Insert log;
- Performance test;
- Transactions;
- Cache and permission verification;
4. Fixed format of decorator
-
Format 1
def decorator(func): # inner function is nested in decorator function def inner(*args, **kwargs): """something before func""" f = func(*args, **kwargs) # The inner function calls the variable func in the scope of the outer function decorator """something after func""" return f return inner # The return value of the outer function decorator is inner (reference to the inner function)
-
Format 2
from functools import wraps def decorator(func): @wraps def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper
5. The evolution of decorators
-
The decorated function is explicitly passed into the decorator, and the decorated function has no parameters and return values;
import time def func(): print("I'm func.") def timer(f): def inner(): start = time.time() f() end = time.time() print(end - start) return inner func = timer(func) # Pass func as an argument to timer decorator and assign the return result to func func() # func(), that is, func is executed
-
Put the decorated function in the next line of the syntax sugar. The decorated function has no parameters and no return value;
import time def timer(f): def inner(): start = time.time() f() end = time.time() print(end - start) return inner @timer # @Timer is called grammar sugar, which is equivalent to func=timer(func) def func(): print("I'm func.") func()
-
Put the decorated function in the next line of the syntax sugar. The decorated function takes 1 parameter and has no return value;
import time def timer(f): def inner(i): start = time.time() f(i) end = time.time() print(end - start) return inner @timer def func(x): print(x) func("Hello, World!")
-
Put the decorated function in the next line of the syntax sugar. The decorated function takes two parameters and has no return value;
import time def timer(f): def inner(*args, **kwargs): start = time.time() f(*args, **kwargs) end = time.time() print(end - start) return inner @timer def func(x, y): print(f"The first argument is {x}, the second is {y}.") func(2, 24)
-
Put the decorated function in the next line of the syntax sugar. The decorated function has multiple parameters and return values;
import time def timer(f): def inner(*args, **kwargs): start = time.time() r = f(*args, **kwargs) end = time.time() print(end - start) return r return inner @timer def func(x, y, z=3): print(f"Arguments are {},{} and {}.") return 'Over' func(1, 2, z=3) print(func(1, 2, z=3))
-
Decorator with parameters, decorated function without parameters, no return value;
def outer(flag): def decorator(f): def inner(*args, **kwargs): if flag: print("Ahead func") r = f(*args, **kwargs) if flag: print("After func") return r return inner return decorator @outer(True) def func(): print("Hello, World!") func()
-
Multiple decorators decorate the same function. The decorated function has no parameters and no return value;
def decorator1(f): def inner(): print('Decorator1, before f') f() print('Decorator1, after f') return inner def decorator2(f): def inner(): print('Decorator2, before f') f() print('Decorator2, after f') return inner @decorator2 @decorator1 def func(): print("I'm func.")
6. Summary of decorators
There are four types of decorators in Python: function decorating function, function decorating class, class decorating function and class decorating class;
-
Function decoration function: the function is passed into the decorator function as a parameter;
def decorator(f): def inner(*args, **kwargs): print(f"function name: {f.__name__}") r = f(*args, **kwargs) return r return inner @decorator # @Decorator is equivalent to addition=decorator(addition) def addition(x, y): return x + y print(addition(3, 7))
-
Function decoration class: class is passed into decorator function as parameter;
def decorator(cls): def inner(*args, **kwargs): print(f"class name: {cls.__name__}") return cls(*args, **kwargs) return inner @decorator # @Decorator is equivalent to Func=decorator(Func) class Func: def __init__(self, item): self.item = item def func(self): print(f"self.a = {self.a}") f = Func('Hello, World!') f.func()
-
Class decoration function: the function is passed into the decorator class as a parameter;
class Decorator: def __init__(self, f): self.f = f def __call__(self, item): print(f"function name: {self.f.__name__}") return self.f(item) @Decorator # @Decorator is equivalent to func = decorator (func). "Call"__ def func(i): return i print(func("Hello, World!"))
-
Class decoration class: the class is passed into the decorator class as a parameter;
class Decorator: def __init__(self, cls): self.cls = cls def __call__(self, item): print(f"class name: {self.cls.__name__}") return self.cls(item) @Decorator # @Decorator is equivalent to func = decorator (func). (call)__ class Func: def __init__(self, v): self.v = v def func(self): print(self.v) f = Func("Hello, World!") f.func()