闭包
闭包条件
1.必须要有内函数
2.内函数必须引用外函数变量
3.外函数必须返回内函数
def outer():
a=10
print(a)
def inner():
print("inner")
return inner
c=outer()
print(dir(c))
print(c.__closure__) #None
def outer(c):
a = 300
def inner():
print(c + a)
return inner
d=outer(10)
d()
print(dir(d))
print(dir(outer))
print(outer.__closure__,d.__closure__)
#(<cell at 0x0000015E8D41FFD0: int object at 0x0000015E8D2AC270>, <cell at 0x0000015E8D41FFA0: int object at 0x0000015E8CC96A50>)
闭包注意事项
def outer():
tmp_list=[]
def inner(name):
tmp_list.append(name)
print(tmp_list)
return inner
d1=outer() #新对象
d1("d1")
d1("d1")
d2=outer() #新对象
d2("d2")
d2("d2")
print(id(d1),id(d2))
print(id(outer(),id(outer()))) #匿名变量 同类型匿名变量的内存地址一般相同
执行时查看变量
在示例中的列表中存放的是inner函数,在调用时查看inner外函数提供的i变量的值,i变量本身应该是要释放的但是由于闭包,被内函数inner所调用,并且inner在f1()f2()f3()才被调用。
def outer():
fs=[]
for i in range(5): <---
def inner(): |
return i*i ----
fs.append(inner)
return fs
f1,f2,f3,f4,f5=outer()
print(f1()) #16
print(f2()) #16
print(f3()) #16
装饰器
装饰器:在不改变源代码的基础上,添加额外功能,本质是闭包
需要传入一个callable对象
# 计算函数执行时间
import time
def func1():
print("fun1")
time.sleep(2)
time1=time.time()
func1()
time2=time.time()
print("执行:",time2-time1,"s")
def func2():
print("func2")
def cost(function):
start=time.time()
function()
end=time.time()
print(f"执行{function.__name__}时间:{end-start}s")
cost(func1)
cost(func2)
装饰器执行时调用方式没有改变(源码没有改变),将被装饰的函数作为参数传递给装饰器,实际执行的是装饰器的内函数,将需要添加的功能写在内函数中。
# 利用装饰器计算执行时间
import time
def cost(f):
def _cost():
start=time.time()
f()
end=time.time()
print(f"执行{f.__name__}时间:{end-start}s")
return _cost
@cost # func1=runtime(func1)
# func1=cost(func1)
def func1():
print("fun1")
time.sleep(2)
@cost
def func2():
print("func2")
time.sleep(2)
func1()
func2()