闭包(closure)是函数式编程的重要的语法结构。
定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).
def outer():
x=10
def inner():#条件一 inner就是内部函数
print(x)#条件二 外部环境的一个变量
return inner #结论 内部函数inner就是一个闭包
f=outer()
f()
#闭包=函数块(inner这个函数)+定义函数时的环境
装饰器:
装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
import time
def show_time(f):
def inner():
start=time.time()
f()
end=time.time()
print('spend %s'%(end-start))
return inner
@show_time #跟这句话是等价的:foo=show_time(foo)
def foo():
print('hello foo')
time.sleep(3)
foo()
@show_time帮我们做的事情就是当我们执行业务逻辑foo()时,执行的代码由粉框部分转到蓝框部分,仅此而已!
装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。
装饰器参数:
装饰器还有更大的灵活性,例如带参数的装饰器:在上面的装饰器调用中,比如@show_time,该装饰器唯一的参数就是执行业务的函数。装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。
如图所示:当你需要区分,有的函数需要不同的功能时(图中是记录到日志),如果你需要这个功能的函数,就可以直接@time_logger,如果不需要这个功能就可以直接@show_time( ):,因为show_time( )是个闭包函数,所以你把他单独拎出来用,丝毫不影响他的功能!!
import time def time_logger(flag=0): def show_time(func): def wrapper(*args, **kwargs): start_time = time.time() func(*args, **kwargs) end_time = time.time() print('spend %s' % (end_time - start_time)) if flag: print('将这个操作的时间记录到日志中') return wrapper return show_time @time_logger(3) def add(*args,**kwargs): time.sleep(1) sum = 0 for i in args: sum += i print(sum) add(2, 7, 5)