python基础8(装饰器)
1、装饰器本质
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
2、装饰器函数
假设要写一个输出函数执行时间的装饰器 def timer(func): def inner(): start = time.time() #这里需要导入time模块 func() end = time.time() print(end - start) def func(): time.sleep(2) #延长函数的执行时间,方便观察 print('----') func = timer(func) func() #实质是已经变成了inner函数
3、语法糖
如果按2写,每次都要写func = timer(func),并且比较不方便,这时候可以使用@语法来进行装饰 #timer和func函数还是按照2中的 @timer def func():... #@timer其实就是相当于执行了func = timer(func)
4、装饰有返回值的函数的装饰器
有时候函数是有返回值的,我们就可以这么做 def timer(func): def inner(): start = time.time() ret = func() #通过赋值给ret来接收func函数的返回值 end = time.time() print(end-start) return ret #因为装饰完的函数其实就是inner函数,所以通过inner的return,就可以将func函数的返回值返回回去 return inner @timer def func(): time.sleep(1) print('hahaha') return 'oh,hsr' ret = func()
5、装饰带参数的函数的装饰器
#要装饰带有参数的函数,只要在内层函数中加上对应的参数就行 def timer(func): def inner(args): start = time.time() func() end = time.time() print(args,end-start) return inner @timer def func(args): time.sleep(1) print('hahaha') func('aaa')
6、固定形式
# 在固定的形式中,我们使用带返回值的,并且不定参数 def wrapper(func): def inner(*args,**kwargs): #这样就可以接收各种参数 #运行被装饰函数之前要做的事 ret = func(*args,**kwargs) #运行被装饰函数之后要做的事 return ret return inner
7、wraps
使用装饰器后,如果我们打印被装饰函数的__name__将会变成装饰器内层函数的名字 @wrapper def func(): pass print(func.__name__) #打印inner 如果要让它变成的原来的,可以在内层函数的上方加上@wraps(func),需要导入functools模块 from functools import wraps def wrapper(func): @wraps(func) def inner(*args,**kwargs): #这样就可以接收各种参数 #运行被装饰函数之前要做的事 ret = func(*args,**kwargs) #运行被装饰函数之后要做的事 return ret return inner
8、带参数的装饰器
如果要使用带参数的装饰器,可以在装饰器函数外面再套一层函数,并把要给装饰器的参数给最外层函数 def wrapper(flag): def wrapper_inner(func): @wraps(func) def inner(*args,**kwargs): #这样就可以接收各种参数 #运行被装饰函数之前要做的事 ret = func(*args,**kwargs) #运行被装饰函数之后要做的事 return ret return inner @wrapper(FLAG) def func(): pass
9、多个装饰器装饰一个函数
多个装饰器装饰一个函数的时候,会先从离函数最近的装饰器开始执行 def wrapper1(func): def inner(): print("---1---") func() print("---1---") return inner def wrapper2(func): def inner(): print("---2---") func() print("---2---") return inner @wrapper2 @wrapper1 def func(): print("func") func() #结果 ---2--- ---1--- func ---1--- ---2---
我们来看一下执行顺序
10、原则
开放封闭原则
开放:对扩展是开放的
封闭:对修改时封闭的