D11 闭包、装饰器
1、闭包
参考 http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html 阮一峰网络日志
闭包概念:
闭包就是能够从外部读取目标函数内部变量的函数。在一些编程语言中,只有函数内部的子函数才能读取局部变量,
因此可以把闭包简单理解成"定义在一个函数(目标函数)内部的函数(闭包函数)"。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
关于判断是否是闭包:
如果此函数拥有自由变量,那么就可以侧面证明其是否是闭包函数了。
def wrapper(): a = 1 def inner(): b = 2 print('使用函数内部变量a:',a) return inner ret = wrapper() ret() # 函数名.__code__.co_freevars 查看函数的自由变量 print(ret.__code__.co_freevars) # 函数名.__code__.co_varnames 查看函数的局部变量 print(ret.__code__.co_varnames) # 函数名.__closure__ 获取具体的自由变量对象,也就是cell对象。 print(ret.__closure__) # cell_contents 自由变量具体的值 print(ret.__closure__[0].cell_contents) 运行结果: 使用函数内部变量a: 1 ('a',) ('b',) (<cell at 0x00000000006BABE8: int object at 0x000007FEE3E77100>,) 1
闭包用途:
闭包可以用在许多地方。它的最大用处有两个。
一个是前面提到的可以读取目标函数内部的变量(装饰器),另一个就是让这些变量的值始终保持在内存中。
(注意:由于闭包会使得目标函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,
可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。)
2、装饰器
def wrapper(func): def inner(*args, **kwargs): """装饰器inner函数的注释部分""" """原函数func执行前的操作""" ret = func(*args, **kwargs) """原函数func执行后的操作""" return ret return inner
什么是装饰器?从字面意思来分析,先说装饰,什么是装饰? 装饰就是添加新的,比如你家刚买的房子,下一步就是按照自己的喜欢的方式设计,进行装修,装饰,地板,墙面,家电等等。什么是器?器就是工具,也是功能,那装饰器就好理解了:就是添加新的功能。
比如我现在不会飞,怎么才能让我会飞?给我加一个翅膀,我就能飞了。那么你给我加一个翅膀,它会改变我原来的行为么?我之前的吃喝拉撒睡等生活方式都不会改变。它就是在我原来的基础上,添加了一个新的功能。
今天我们讲的装饰器(装修,翅膀)是以功能为导向的,就是一个函数。
被装饰的对象:比如毛坯房,我本人,其实也是一个函数。
所以装饰器最终最完美的定义就是:在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。
参考 https://www.cnblogs.com/jin-xin/articles/10871410.html 太白老师讲装饰器
def wrapper(func): def inner(*args, **kwargs): """装饰器inner函数的注释部分""" """原函数func执行前的操作""" ret = func(*args, **kwargs) """原函数func执行后的操作""" return ret return inner @wrapper def func(): """原函数func的注释部分""" print('我是原函数func') func() print('--------') print(func.__name__, type(func.__name__)) print(func.__doc__) 执行结果: 我是原函数func -------- inner <class 'str'> 装饰器inner函数的注释部分
恢复装饰器装饰后的原函数名的方法:
1.利用func.__name__
def wrapper(func): def inner(*args, **kwargs): """装饰器inner函数的注释部分""" """原函数func执行前的操作""" ret = func(*args, **kwargs) """原函数func执行后的操作""" return ret inner.__name__ = func.__name__ inner.__doc__ = func.__doc__ return inner @wrapper def func(): """原函数func的注释部分""" print('我是原函数func') func() print('--------') print(func.__name__, type(func.__name__)) print(func.__doc__) 执行结果: 我是原函数func -------- func <class 'str'> 原函数func的注释部分
2.利用functool模块的warp装饰器
import functools def wrapper(func): @functools.wraps(func) def inner(*args, **kwargs): """装饰器inner函数的注释部分""" """原函数func执行前的操作""" ret = func(*args, **kwargs) """原函数func执行后的操作""" return ret return inner @wrapper def func(): """原函数func的注释部分""" print('我是原函数func') func() print('--------') print(func.__name__, type(func.__name__)) print(func.__doc__) 执行结果: 我是原函数func -------- func <class 'str'> 原函数func的注释部分