这里my_decorator()为装饰器,将greet()包含在其中,改变了greet函数的行为,但是原函数greet并没变。不改变原函数的情况下,改变函数的行为。
调用方法:
1、像greet函数中进行调用
greet = my_decorator(greet) greet()
2、像greet2函数中进行调用 @my_decorator
这里的@称之为语法糖
举例:如果想让一个函数执行多次,可以写成
def repeat(num): def my_decorator(func): def wrapper(*args, **kwargs): for i in range(num): print('wrapper of decorator') func(*args, **kwargs) return wrapper return my_decorator @repeat(4) def greet(message): print(message) greet('hello world') # 输出: wrapper of decorator hello world wrapper of decorator hello world wrapper of decorator hello world wrapper of decorator hello world以上可知,原函数元信息改变,greet函数被wrapper函数取代
解决:采用内置装饰器@functools.wraps(func),将原函数的元信息拷贝到对应装饰器函数
import functools def my_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('wrapper of decorator!') func(*args, **kwargs) return wrapper @my_decorator def greet(message): print(message) greet.__name__ # 输出 'greet'主要依赖于函数_call_()
import time class TimeCount: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): start_time = time.time() self.func() end_time = time.time() print(f'执行函数时间为:{start_time-end_time}') @TimeCount def greet(): time.sleep(2) greet()执行顺序:从里向外
decorator1(decorator2(decorator3(func))) import functools def my_decorator1(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('execute decorator1') func(*args, **kwargs) return wrapper def my_decorator2(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('execute decorator2') func(*args, **kwargs) return wrapper @my_decorator1 @my_decorator2 def greet(message): print(message) greet('hello world') # 输出 execute decorator1 execute decorator2 hello world身份认证、日志、缓存、输入合法性检查等