一、装饰器的初成
1、一个需要做装饰器的示例
import time def func(): time.sleep(0.1) #让程序暂停执行0.1s print('你好') def timer(f): #运行f函数,并计算f函数的执行时间----这样做要修改全部的函数名称为timer,非常消耗时间 start = time.time() #1533213779.934297,从1970到现在经过的秒数----获取当前的时间戳 f() end = time.time() print(end - start) timer(func)
2、使用装饰器的方法解决以上问题,好处是:只要 func1 = timer(func1) 赋值不同函数,就可以实现计算多个函数的执行时间的功能
- 不需要修改函数的调用方式,但是可以在已有的函数前后添加一些公共功能
- timer就是一个装饰器函数,只是对一个函数,有装饰作用,被装饰的函数是f
import time def func1(): time.sleep(0.1) print('func1') def timer(f): def inner(): start = time.time() f() end = time.time() print(end - start) return inner func1 = timer(func1) #实际上func1指向了inner的内存地址 func1() #执行inner函数
二、开放封闭原则
1、开放:对扩展是开放的
2、封闭:对修改是封闭的----如果修改了老的函数,可能影响之前已经使用该函数的功能,因此不允许修改
三、一个基础的装饰器的最终形成和固定格式
1、不完整的装饰器
不完整的装饰器:没有返回值 import time def timer(f): #装饰器函数 def inner(): start = time.time() f() end = time.time() print(end - start) return inner @timer #语法糖,@装饰器函数名。在被装饰函数上方紧贴着装饰器,相当于 func1 = timer(func1) def func1(): time.sleep(0.1) print('func1') return '你好呀' print(func1()) #func1相当于inner,因此返回值是inner的返回值None,拿不到func1本身的返回值
2、完整的装饰器
#完整的装饰器 import time def timer(f): #装饰器函数 def inner(): start = time.time() ret = f() end = time.time() print(end - start) return ret return inner @timer #语法糖,@装饰器函数名。在被装饰函数上方紧贴着装饰器,相当于 func1 = timer(func1) def func1(): time.sleep(0.1) print('func1') return '你好呀' print(func1()) #func1相当于inner,因此返回值是inner的返回值None,拿不到func1本身的返回值
3、注意,如果被装饰函数有参数,则 被装饰函数、装饰器函数、装饰器函数中调用的被装饰函数、执行被装饰函数 4个位置都需要加上参数
4、如果被装饰函数有多个参数,则需要遵循 形参、实参的规则(注意灵活使用 *args、**kwargs)
#完整的装饰器----多个被装饰参数,携带多个位置参数和关键字参数 import time def timer(f): #装饰器函数 def inner(*args,**kwargs): #*args、**kwargs作为形参,实现 多个元素-单个元组、字典 的操作 start = time.time() ret = f(*args,**kwargs) #*args、**kwargs作为实参,实现 单个元组、字典-打散到单个元素的操作 end = time.time() print(end - start) return ret return inner @timer def func1(a): time.sleep(0.1) print('func1',a) return '你好呀' @timer def func2(a,b): time.sleep(0.1) print('func1',a,b) return '你好呀' print(func1('func1-a')) print(func2('func2-a','func2-b'))
5、装饰器的固定格式
import time def wrapper(f): #装饰器函数,f是被装饰的函数名----形参 def inner(*args,**kwargs): '''在被装饰函数之前要做的事''' ret = f(*args,**kwargs) '''在被装饰函数之后要做的事''' return ret return inner @wrapper #语法糖,@装饰器函数名,等同于 func = wrapper(func),func被赋值为inner def func(a,b): #被装饰的函数 time.sleep(0.1) print('func',a,b) return 'func结束啦' print(func('ddfs',22))