闭包函数及装饰器
一.闭包函数
闭包函数:
1.闭:定义在函数内部的函数
2.包:内部函数引用了外部函数作用域的名字
可以用闭包来给函数传参
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def outter(x): def inner(): print(x) return 100 return inner res = outter(1233) print(res())
二.装饰器
装饰器就是闭包函数的一种应用场景
1.为什么要用装饰器
开放封闭原则:
开放:对扩展开放
封闭:对修改封闭
2.装饰器简介
装饰器(可调用对象)需要遵守的两个原则:
1.不改变被调用装饰对象的源码
2.不改变被调用装饰对象调用方式
装饰器的目标:为可调用对象增加新的功能。(就像是给一个丑陋的盒子,用一层精美的包装自装扮起来)
2.装饰器模板
装饰器的通用写法
无参
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from functools import wraps def outter(func): @wraps(func) def built_inner(*args, **kwargs): print("函数执行之前的操作") res = func(*args, **kwargs) print("函数执行之后的操作") return res return built_inner @outter def index(): print("index") index() print(help(index)) # 查看函数的注释 print(index.__name__)
有参
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from functools import wraps def wrapper(source): def outter(func): @wraps(func) def built_inner(*args, **kwargs): print("函数执行之前的操作") res = func(*args, **kwargs) print("函数执行之后的操作") return res return built_inner return outter @wrapper(1) def index(): print("index") index() print(help(index)) # 查看函数的注释 print(index.__name__)
3.语法糖
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@outter # @outter 等价于 for_rang = outter(for_rang) def for_rang(): time.sleep(1) for i in range(1, 10): for j in range(1, i + 1): print("%s*%s=%2s " % (i, j, i * j), end="") print()
语法糖在书写的时候应该与被调用的对象紧紧挨着 ,两者之间不要有空行。
4.多层装饰器
装饰器在装饰顺序 从下往上
装饰器执行时顺序 从上往下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def outter1(func1): print('加载了outter1') def wrapper1(*args,**kwargs): print('执行了wrapper1') res1=func1(*args,**kwargs) return res1 return wrapper1 def outter2(func2): print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2(*args,**kwargs) return res2 return wrapper2 def outter3(func3): print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) return res3 return wrapper3 @outter1 # index = outter1(wapper2) @outter2 # wrapper2 = outter2(wrapper3) @outter3 # wrapper3 = outter3(最原始的index函数内存地址) def index(): print('from index') index()
5.装饰器的伪装
用户查看被装饰函数的函数名和注释时看到的就是被装饰函数和它的注释
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from functools import wraps def outter(func): @ wraps(func) def get_time(*args, **kwargs): """ this is get_time :param args: :param kwargs: :return: """ start = time.time() res = func(*args, **kwargs) end = time.time() print(end - start) return res return get_time def wrapper1(func): @wraps(func) def confirm_(*args, **kwargs): """ this is confirm :param args: :param kwargs: :return: """ username = input("username>>:").strip() psw = input("password>>:").strip() if username == "jason" and psw == "123": res = func(*args, **kwargs) return res else: print("输出错误") return confirm_