闭包函数与装饰器
一、闭包函数
定义在函数内部的函数,并且该函数包含对外部函数作用域中名字的引用,该函数就称为闭包函数。
一个持有外部环境变量的函数就是闭包,闭包=函数块+定义函数时的环境。
闭包函数是一个能记住嵌套作用域变量值的函数,尽管作用域已经不存在
工厂函数定义了一个外部的函数,这个函数简单的生成并返回一个内嵌的函数,仅仅是返回却不调用,因此通过调用这个工厂函数,可以得到内嵌函数的一个引用,内嵌函数就是通过调用工厂函数时,运行内部的def语句而创建的。
闭包的作用:
1、当闭包执行完后,仍然能够保持住当前的运行环境。希望函数的每次执行结果,都是基于这个函数上次的运行结果。
2、闭包可以根据外部作用域的局部变量来得到不同的结果。这有点像一种类似配置功能的作用,可以修改外部的变量,闭包根据这个变量展现出不同的功能。比如有时需要对某些文件的特殊行进行分析,先要提取出这些特殊行。
闭包中是不能修改外部作用域的局部变量的,作用域关系在函数定义阶段就规定死了,与调用位置无关。
二、装饰器
装饰器其实就是一个闭包函数,一个用来包装函数的函数,返回一个修改之后的函数对象,将其重新赋值原来的标识符,并永久丧失对原始函数对象的访问。
装饰器与被装饰对象均是可以任意可调用的对象,可以是函数
装饰器的作用:
在不修改被装饰对象源代码与调用方式前提下,为被装饰对象添加新功能
一般情况下,装饰器主要可以用在缓存、日志、URL路由和权限校验等常见的功能上
1)、缓存:假设有一个函数的运行时间比较长,为了节省时间,我们可以对其结果进行缓存
2)、单例模式的优雅实现
3)、线程装饰器实现简单异步:将被装饰的函数进行异步处理,耗时的操作将在新线程中运行,web服务可以直接返回响应,无需等待
4)、失败重试机制:利用装饰器,对某些函数增加重试功能
装饰器基本形式模板:
def outter(func):
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper
语法糖:@放在被装饰对象的正上方
叠加多个装饰器:
@
@
被装饰对象
当有多个装饰器时,装饰顺序按靠近被装饰对象顺序执行。调用时由外而内,执行顺序和装饰顺序相反
在装饰器中,被装饰函数的元属性变成了装饰函数(装饰器最终返回的那个函数)的信息,为了消除这种副作用,可以使用functools模块的wraps方法,对装饰器最终返回的那个函数进行装饰
模板:
from functools import wraps
def outter(func):
@wraps(func)
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
return res
return wrapper