闭包:引用了自由变量的函数。这个被引用的自由变量将和这个闭包函数一同存在,即使离开了创造它的环境也不例外。
闭包用语言描述:就是调用了函数A,这个函数A返回一个函数B给你,函数B就叫做闭包。调用函数A时传递的参数以及A函数中定义的局部变量就是自由变量,可以在B中使用,但是不能进行修改。如果需要改写自由变量必须申明为nonlocal
闭包可以描述为funcA(paramsA, funcB(paramsB))->funcB
装饰器原理:
1、一个函数定义了装饰器,则装饰器立即执行(函数调用)。
2、同时定义多个装饰器时,装饰器执行顺序为从下(被装饰函数)往上立即执行。
3、定义多个装饰器最后获得的函数是最上面那个装饰器函数所返回出来的函数。
4、下层函数返回的闭包函数作为上层函数的参数
5、定义多个装饰器,一般执行顺序为从上往下执行,
上层函数的闭包函数调用下层闭包函数,最下面那个闭包函数调用被装饰函数(业务逻辑函数)
代码说明
#italic_wrapped: 内层装饰器makeitalic的返回函数(闭包函数)
def make_bold(italic_wrapped)
print('call makebold()')
#这个是最外层的装饰器闭包函数,最终执行的是这个函数
def bold_wrapped(bold_name):
print("call %s()"%italic_wrapped.__name)
#do something check ....
#应用可以执行第一层过滤(比如登陆检测)
return "<b>" + italic_wrapped(bold_name) + "</b>"
#business_fn:真正的业务逻辑函数
def make_italic(business_fn):
print('call make_italic()')
#这个是最内层的装饰器闭包函数,也是最靠近业务逻辑的函数
def italic_wrapped(italic_name):
print("call %s()"%business_fn.__name)
#do something check ...
#执行业务逻辑之前进行最后一层过滤(比如权限验证)
#调用业务逻辑函数进行业务处理
return "<i>" + business_fn(italic_name)
@make_bold #外层装饰器函数,编译时马上调用 bold_wrapped = make_bold(italic_wrapped)
@make_italic #内层装饰器函数,编译时马上调用 italic_wrapped = make_italic(business_fn)
#业务逻辑处理函数
def business_fn(name):
return 'hello world ' + name
#print(business_fn("business"))
#上面这个代码注释也会马上执行装饰器 @make_italic和@make_bold输出下面内容
call make_italic()
call make_bold()
print(business_fn("business"))
函数包装过程:
bussiness_fn
->make_italic(bussiness_fn) = italic_wrapped
->make_bold(italic_wrapped) = bold_wrapped
最终bussiness_fn("bussiness")函数调用相当于bold_wrapped("bussiness")调用,
只不过是bold_wrapped这个闭包函数使用了一个相同的名字bussiness_fn,
所以看起来就是原函数调用方式没有发生任何变化,只是额外增加了新的外包函数
bold_wrapped("bussiness")函数调用流程如下
1、进入bold_wrapped函数,打印即将调用的装饰器函数名称 call italic_wrapped()
2、执行内层装饰器italic_wrapped函数
3、进入italic_wrapped函数,打印即将调用的业务逻辑函数call business_fn()
4、执行业务逻辑函数business_fn
5、返回业务逻辑数据
6、返回内层装饰器数据italic_wrapped
7、返回外层装饰数据bold_wrapped
8、返回最终数据
#执行结果
call make_italic()
call make_bold()
call italic_wrapped()
call business_fn()
<b><i>hello world business</i></b>