1.闭包
*定义:
闭包是指一个函数内部使用了外部定义的变量,则函数体与外部变量统称为闭包。
*闭包形成条件:
内部函数使用了外部函数的临时变量,外函数要返回内函数的引用
eg:(函数结束时会释放所有局部变量,但是闭包可以让外函数将外部变量转移给内部,避免其被立马回收释放。)
def outer_func(): #定义了外函数
tmp = 10 #外函数有临时变量tmp
def inner_func(): #外部函数内部定了一个函数
print(tmp) #内函数使用了外部函数
return inner_func #外函数要返回内函数的引用
test = outer_func() #调用外函数,用test接收返回值,还未执行内部函数体
test() #test接收的是inner_func(),所以test调用并执行内函数
eg: 其实这已经是一个装饰器啦!!!
def make(li):
def cur_sum():
csum = 0
for num in li:
csum += num
return csum
return cur_sum
li = [x for x in range(10)]
result = make(li) #调用make函数,还未调用cur_sum函数,所以不执行内部函数体
print(result()) #result = cur_sum函数引用,此处调用result()才执行内部函数体
在闭包中若想修改外部局部变量,要用nonlocal关键字声明变量
def outer_func():
tmp = 10
def inner_func():
nonlocal tmp #用nonlocal声明被修改的变量
tmp += 1 #修改变量
print(tmp)
return inner_func
*作用:
构造装饰器、实现面向对象、实现单利模式。当函数中变量和函数较少且其中某个功能常用时,可以用闭包来封装;当变量和函数较复杂时,用类来实现。
2.装饰器
*用途:
代码具有封闭开放性原则:当某一段代码已实现某一功能,而我们想额外添加新的功能 时,可以在不改动原代码基础上(封闭)增加额外功能(开放),保证开发效率及代码稳定性。
*装饰器通用写法:
def ty(func): 1
def ty_in(*args, **kwargs): 3
ret = func(*args, **kwargs) #以内函数的参数作为参数传递,调用传入的外函数
return ret #最终返回func(*args, **kwargs)的结果
return ty_in 2
#执行顺序:1--》2--》3执行内部并返回作用结果
*装饰器的特性:
1.把被装饰的函数替换为其他函数; 2.装饰器在加载模块时就被立即执行; 3.基于类实现的装饰器必须实现__call__和__init__两个内置方法。
缺点:会更改原函数的元信息(__name__,参数列表等);不能装饰@classmethod或@ststicmethod已经装饰过的方法;位置错误的代码不能在装饰器外添加逻辑功能。
*典型的原始时间装饰器:
import time
def outer_func(f):
def inner_func():
time1 = time.time()
f()
time2 = time.time()
return time2 - time1
return inner_func
@outer_func() #相当于:test = outer(test),即把下面的函数当做outer_func()的参数f传入并运算
def test():
print('test')
#本质上为:
import time
def outer_func(f):
def inner_func(*args, **kwargs):
time1 = time.time()
ret = f(*args, **kwargs) 2.内函数的参数作为外函数的参数并执行
time2 = time.time()
res = time2 - time1
print(res) #返回函数执行的时间长短
return ret 3.返回作用结果
return inner_func 1.外函数返回内函数的引用
eg:假设函数f1可以实现打印乘法表功能
def show(f):
def show_in():
f()
return show_in
def f1():
pass
if __name__ == '__main__':
f1 = show(f1) #将f1作为外函数show的参数,返回内函数的引用
f1() #开始执行内函数并返回执行结果
也可以写作:
def show(f):
def show_in():
f()
return show_in
@show #相当于将下面的函数作为参数传入外函数show中
def f1():
pass
if __name__ == '__main__':
f1()