装饰器补充
一、通用装饰器回顾
def wrapper(func): def inner(*args,**kwargs): '执行目标函数之前要执行的内容' ret = func(*args,*kwargs) '执行目标函数之后要执行的内容' return ret return inner @wrapper #相当于target_func = wrapper(target_func) 语法糖 def target_func(): print('我是目标函数') #调用目标函数 target_func()
执行过程:
1、程序从上到下,当执行到@wrapper时,把函数作为参数传递给wrapper函数,得到inner函数,重新赋值给target_func(把inner赋值给target_func)
2、当执行到target_func时,我们实际上执行的是inner函数,inner函数会先执行目标函数之前的代码,然后在执行你的目标函数,执行完目标函数最后执行的是目标函数之后的代码。
二、函数的有用信息
1、给函数添加注释:说明函数的意义
# def eat(food): # """ # 吃函数: 把传递进来的内容吃掉 #函数的注释,就是这个函数是干嘛的 # :param food: 食物 #参数 food 是什么意思 # :return: None #返回什么东西 # """ # print("我要吃", food) # eat("烤肉")
2、获取函数的相关信息
def eat(food): """ 吃函数 :param food:水果 :return: """ print('我要吃',food) eat('西瓜') print(eat.__doc__) #获取函数的文档注释 函数名._doc_ print(eat.__name__) #获取函数名称 函数名._name_ 执行结果: 我要吃 西瓜 吃函数 :param food:水果 :return: eat
from functools import wraps #引入函数模块 def wrapper(fn): @wraps(fn) # 这个代码的作用. 把inner的__name__ __doc__ 替换成fn的__name__ def inner(*args, **kwargs): print("我是前面") ret = fn(*args, **kwargs) print("我是后面") return ret return inner @wrapper # func = wrapper(func) #@wrapper 把func的_name_改成了inner,@wraps 把inner的_name_改成了func def func(): print("我是func") func() print(func.__name__)
三、装饰器传参:
from functools import wraps def wrapper_out(flag): def wrapper(fn): # fn: 被装饰的函数 @wraps(fn) def inner(*args, **kwargs): # inner => 最终执行的 if flag == True: print("打电话问问金老板.安全不安全啊") ret = fn(*args, **kwargs) # fn 被装饰的函数 print("金老板骗我") return ret else: ret = fn(*args, **kwargs) # if 条件不成立,走else return ret return inner return wrapper #传递True和False来控制装饰器内部的运行结果 @wrapper_out(True) # 带参数的装饰器的执行流程: 先执行@后面的函数. 然后再加上@ 组装成语法糖 def yue(): # inner print("约一约") yue()
四、多个装饰器装饰同一个函数
def wrapper(func): def inner(*args,**kwargs): print('0') ret = func(*args,**kwargs) print('00') return ret return inner def wrapper1(func): def inner(*args,**kwargs): print('1') ret = func(*args,**kwargs) print('11') return ret return inner def wrapper2(func): def inner(*args,**kwargs): print('2') ret = func(*args,**kwargs) print('22') print('222') return ret return inner @wrapper1 打印顺序:按装饰器顺序从上往下(执行目标函数前),执行目标函数 ,在从下往上(执行目标函数后) @wrapper2 @wrapper def target_func(): print('我是熊猫') target_func()
执行结果:
1 第三层装饰器前
2 第二层装饰器前
0 第一层装饰器前
我是熊猫
00 第一层装饰器后
22 第二层装饰器后
222 第二层装饰器后
11 第三层装饰器后