python:闭包,装饰器
闭包:
闭包只能存才嵌套函数中
内层函数对外层还输非全局变量的引用,就会形成闭包
被引用的非全局标量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系
自由变量不会在内存中消失
# __code__.co_freevars : 函数的属性,获取函数中的自由变量 def wrapper(): l = [] #这个l 是个自由变量,在函数外部是不能改变 l 的值 def inner(val): l.append(val) return sum(l)/len(l) return inner ret = wrapper() print(ret.__code__.co_freevars) # ('l',),可以当做判断一个函数是不是闭包 def wrapper(a,b): # 这里a,b也是自由变量 def inner(): res = a+b return res return inner ret = wrapper(2,3) print(ret.__code__.co_freevars) # ('a', 'b')
装饰器
装饰器:在不改变 原函数代码 以及 调用方式 的前提下,为其增加新的功能 import time def index(): time.sleep(2) print('welcom login') # 模拟登陆 def timmer(f): # 这里用到了闭包。这里f是个自用变量,自由变量不受函数外部影响 def inner(): start_time = time.time() f() end_time = time.time() print(f'测试函数的执行效率{end_time-start_time}') return inner index = timmer(index) # 将函数名index作为参数传递给timmer(f),实际上传递的是index指向的内存地址,即 变量f指向了index指向的内存地址。然后将返回值inner重新赋值给index,index指向的内存地址变成了inner()函数的内存地址 index() # 语法糖:@,用来当做装饰器装饰函数 ,@timmer()相当于 index = timmer(index) import time def timmer(f): def inner(): start_time = time.time() f() end_time = time.time() print(f'测试函数的执行效率{end_time-start_time}') return inner @timmer # 代码执行到这里的时候,会向下多执行一行 def index(): time.sleep(2) print('welcome login') index() #带参数有返回值的装饰器 import time def timmer(f): def inner(*args,**kwargs): st = time.time() ret = f(*args,**kwargs) et = time.time() print(f'login application run time{et - st}') return ret return inner @timmer def login(name): time.sleep(1) print(f'welcome to blog,{name}!!') login('alex') #标准版的装饰器 def wrapper(f): def inner(*args,**kwargs): ''' 添加额外功能,执行被装饰函数之前的操作''' ret = f(*args,**kwargs) '''添加额外功能,执行被装饰函数之后的操作''' return ret return inner # 通过改变一个参数,控制代码是否执行 import time def change_start(a): def wrapper(f): def inner(*args,**kwargs): if a: st = time.time() ret = f(*args,**kwargs) et = time.time() ti = et - st return ti else:return 'no run' return inner return wrapper @change_start(False) # 这里传递参数,来控制被装饰函数是否执行 def login(): time.sleep(1) print(login())