闭包函数
一个定义在一个函数内部的函数,且内部的函数有使用来自外部函数的名称空间中使用的变量名,则这个内部函数称为闭包函数。
name = 'jack' #name不在函数内,属于全局名称空间,index不是闭包函数
def func():
def index():
print(name)
def func():
name = 'jack' #name在外部函数内,属于局部名称空间,index是闭包函数
def index():
print(name)
def func(name): #name从外部空间输入到局部空间中,也属于局部空间,index也是闭包函数
def index():
print(name)
当我们需要在全局空间调用闭包函数时,可以先通过外部函数的return来返回内部函数名。例:
通过return返回内部函数名并赋值外部空间的变量res,相当于把变量res变成了内部函数index,就可以用变量res来调用内部函数了。
def func(name):
def index():
print(name)
return index #返回内部函数代码体
res = func() #将代码体赋值给变量
res() #此时变量内保存的就是内部函数的代码体
装饰器
装饰器的简介
在不改变被装饰的对象的调用方式和内部代码的情况下给目标对象添加新的代码功能,相当于在不改变代码添加新的扩展功能。
对于一个在工程前期就制作好的函数体,在后期需要添加新功能时直接修改代码可能会产生bug,这时用装饰器就可以避免bug的产生。
关键字time
有些关键字无法直接调用,需要使用import取消锁定,time就是其中之一。
import time
time.time
#会输出一个数值,是从1970年1月1日0时0分0秒一直到当前时间所经历的秒数
time.sleep()
#让代码待机一段时间再继续执行,在括号内输入待机的具体秒数
装饰器的逐步推导
首先编写一个简单的函数体,效果是计算函数执行花费的时间。
import time
def get_time():
def index():
time.sleep(3)
start_time = time.time()
index()
end_time = time.time()
print(end_time - start_time)
此时在任意位置调用函数get_time就能打印函数index的执行时间,而如果此时突然需要打印其他函数的执行时间,可以调整函数的输入参数,让需要打印的函数从形式参数输入到内部函数中,这样就能更加灵活的调用函数了。
import time
def get_time(xxx):
start_time = time.time()
xxx()
end_time = time.time()
print(end_time - start_time)
def index():
time.sleep(3)
def abc():
time.sleep(5)
get_time(index)
get_time(abc)
但是想要添加装饰器的前提是不改变函数体的调用方式,添加形式参数之后就改变了原函数的调用方式,所以应该更换成闭包函数。
import time
def outer(xxx):
def get_time():
start_time = time.time()
xxx()
end_time = time.time()
print(end_time - start_time)
return get_time
def index():
time.sleep(3)
def abc():
time.sleep(5)
index = outer(index)
index()
将原函数作为内部函数,外面添加一个外部函数,使用闭包函数就能避免原函数的调用方式更改了。
如果想要让该函数同时打印几个不同的函数执行的实时间,那么需要在外部函数添加可变参数*。
import time
def outer(xxx):
def get_time(*args,**kwargs):
start_time = time.time()
xxx(*args,**kwargs)
end_time = time.time()
print(end_time - start_time)
return get_time
def index():
time.sleep(3)
def abc():
time.sleep(5)
index = outer(index)
index()
但是根据这个函数的逻辑,虽然能成功返回函数运行时间,但是原本的函数index和abc对应的名字已经被改成了get_time,导致无法取得原本函数内部的输出,所以需要重新添加一个分支,既能输出函数执行时间,又不会覆盖原本函数的输出。
import time
def outer(xxx):
def get_time(*args,**kwargs):
start_time = time.time()
res = xxx(*args,**kwargs)
end_time = time.time()
print(end_time - start_time)
return res
return get_time
def index():
time.sleep(3)
def abc():
time.sleep(5)
index = outer(index)
index()
由于变量xxx是get_time的输出值,将其赋值给另一个变量来接收就可以防止其覆盖全局空间的函数名。
装饰器语法简写
如例题所示,装饰器最常用的代码为下
index = outer(index)
用于接收闭包函数到全局空间中,而这个代码可以使用简写来方便输入。
import time
def outer(xxx):
def get_time(*args,**kwargs):
start_time = time.time()
res = xxx(*args,**kwargs)
end_time = time.time()
print(end_time - start_time)
return res
return get_time
@outer
def index():
time.sleep(3)
@outer
def abc():
time.sleep(5)
@outer 等价于 index = outer(index)