今日学习的内容:闭包函数、装饰器。
闭包函数
闭包函数就是两个函数的嵌套,两个函数分为内部函数和外部函数,当外部函数的返回值是内部函数的引用的时候,就构成了闭包的情况。
def func(): # 外部函数 name = 'jason' def inner(): # 内部函数 print(name) # 内部函数的执行 return inner # 返回值为内部函数 f = func() # 外部函数引用了内部函数 f()
闭包函数要满足一下两点:
1、定义在函数内部的函数。
2、内部函数引用外部函数名称空间作用域的名字。
要点:函数在定义阶段名字的查找顺序就已经固定死了,不会因为函数调用位置的变化而改变。
给函数传参会用到的两种方式: 1、直接传参 def index(name): print(name) 2、闭包 def outter(name): name = 'jason' def index(): print(name) return index
装饰器
装饰器的作用是给被装饰的对象添加新的功能。
装饰器的开放封闭原则:开放(对扩展开放)、封闭(对修改封闭)
装饰器(调用对象)必须遵循的两个原则:
1.不改变被装饰对象的源代码
2.不改变被装饰对象(可调用对象)调用方式
#小知识点 import time print(time.time()) # 时间戳,显示的是当前时间距离1970-1-1 00:00:00相差的秒数 time sleep(3) # 让你的程序暂停3秒再执行 print('NB')
我们先写一个函数
import time def index(): time.sleep(3) print('时间到了,gogogo!') print(index())
我们要添加一个功能,用来统计index函数执行的时间
start = time.time() # 记录index开始的时间 index() end = time.time() # 记录index结束的时间 print('index run time:%s'%(end-start)) # 打印出运行index()的时间
我们把这个功能写到一个函数里面然后要让我们在直接调用index()的时候能加入这个
import time def index(): time.sleep(3) print('时间到了,go go go!') def outter(func): # func = 最原始的index函数的内存地址 def get_time(): start = time.time() func() # func = index函数的内存地址() 直接调用 end = time.time() print('index run time:%s'%(end-start)) return get_time index = outter(index) # outter(最原始的index函数内存地址),本质上返回了get_time # index指向get_time函数的内存地址 index() #本质上调用了get_time函数,get_time()中的func()才调用的是原函数
我们通过命名了一个与index()同名的变量名达到了目地,接下来要让它的返回值也与index()相同。
import time def index(): time.sleep(3) print('时间到了,go go go!') return 'index' def outter(func): # func = 最原始的index函数的内存地址 def get_time(*args, **kwargs): # args = ('egon',) kwargs = {} start = time.time() res = func(*args, **kwargs) # 最原始的index函数的内存地址() 直接调用 end = time.time() print('func run time:%s'%(end-start)) return res return get_time index=outter(index) print(index())
pychram中的语法糖
@outter # index = outter(index) outter(最原始的index的函数的内存地址) def index(): time.sleep(3) print('时间到了,go go go!') return 'index'
@outter就是语法糖,在@的后面就是你装饰器的最外层的函数名,然后语法糖会把紧挨着它的下面的函数名当做参数进行调用
装饰器修复技术
from functools import wraps def outter(func): @wraps(func) # 装饰器修复技术,加载内层函数的正上方 def inner(*args,**kwargs):
在加入了装饰器修复技术后用户查看到的就是被装饰函数的本身,而且查看到的注释也是被装饰函数本身的注释。
装饰器的模板
1.无参装饰器 from functools import wraps def outter(func): @wraps(func) def inner(*args,**kwargs): # * **在形参中使用 # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner 2.有参装饰器(最复杂就三层) def wrappers(data): # data = 'file' def outter(func): def inner(*args,**kwargs): if data == 'file': # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner return outter