def func1():
li = []
def func2(x):
li.append(x)
return li
ruturn func2
f = func1()
print(f(100)) # [100]
print(f(100)) # [100, 100]
print(f(100)) # [100, 100, 100]
#li就是自由变量,并没有消失,但无法从函数外访问。
print(func.__code__.co_freevars)
# 只要返回值有自由变量那么就是闭包
例如:给函数添加一个功能用来测试函数的执行效率,计算效率的方法就是用函数执行完毕后的时间减去函数执行前的时间
import time
print(time.time()) # 显示此时此刻距离1970年1月1日0点0分0秒的秒数,也叫时间戳。
# 第一个版本
import time
def func1():
time.sleep(1) # 让程序停止1秒,模拟程序的执行耗时
print(‘Hello,word!‘)
start_time = time.time()
func1()
end_time = time.time()
print(end_time - start_time)
# 实现了测试效率的功能,但代码写死,只能测试func1
# 第二个版本
import time
def func1():
time.sleep(1)
print(‘Hello,word!‘)
def timer(f):
start_time = time.time()
f()
end_time = time.time()
print(end_time - start_time)
timer(func1)
# 实现了功能并且可以测试其他函数,但改变了函数func的调用方式
# 第三个版本
import time
def func1():
time.sleep(1)
print(‘Hello,word!‘)
def timer(f):
def inner():
start_time = time.time()
f() # 装饰器的本质就是闭包,此时参数f是个自由变量
end_time = time.time()
print(end_time - start_time)
return inner
func1 = timer(func1) # 传进函数内的func1并不会改变
func1() # 此时的func1()相当于inner()
# 在未改变原代码和调用方式的基础上,增加了功能,但多了一个赋值语句func1 = timer(func1)
# 若是调用其他函数则需要重复写代码,所以Python做了个优化:提出来语法糖的概念
# 第四个版本
import time
def timer(f): # timer 就是个装饰器
def inner():
start_time = time.time()
f()
end_time = time.time()
print(end_time - start_time)
return inner
@timer # 相当于 func1 = timer(func1) 写在函数之前
def func1():
time.sleep(1)
print(‘Hello,word!‘)
return ‘in func1‘
print(func1())
# 此时func1实际上为inner,原func1的返回值是返回给原func1,并非返回给inner,所以值为None
# 加语法糖才会调用timer
def func2():
time.sleep(1)
print("I‘m fine")
return ‘in func1‘
func2()
# 此时迭代器基本实现,但会影响函数返回值,并且影响传参,还需要继续修改
# 版本六
import time
def timer(f):
def inner():
start_time = time.time()
r = f() # func1的调用实际在这一行,所以将func()的返回值赋值给r,将r返回给inner
end_time = time.time()
print(end_time - start_time)
return r
return inner
@timer
def func1():
time.sleep(0.5)
print(‘hello‘)
return ‘in func1‘
print(func1())
# 此时func1实际上为inner,inner的返回值为r,也就是原func1的返回值
# 没有改变func1的调用方式,也没有改变func1的返回值,符合装饰器定义,接下来需要解决向func1传参
# 版本七
import time
def timer(f):
def inner(*args,**kwargs): # 被装饰函数可能会接收各种参数,利用*的魔性用法可以接收所有参数
start_time = time.time()
r = f(*args,**args) # *放在函数调用时表示打散
end_time = time.time()
print(end_time - start_time)
return r
return inner
@timer
def func1(n,a=‘18‘):
time.sleep(0.5)
print(f‘hello,{n},今年{a})
return ‘in func1‘
print(func1(‘李白‘,n=‘33‘))
# 此时装饰器timer已全部完成,当需要测试某函数的执行效率时,则在被装饰函数定义前加上语法糖语句即可
# 最后标准格式的装饰器
def wrapper(f):
def inner(*args,**args):
‘‘‘被装饰函数执行前添加的功能‘‘‘
ret = f(*args,**args)
‘‘‘被装饰函数执行后添加的功能‘‘‘
return ret
return inner
原文:https://www.cnblogs.com/ChiRou/p/13348143.html