day11.装饰器初识
1.开放封闭原则
原则: 开放封闭原则,对扩展是开放的,对修改是封闭的。
封版概念:当写好一个功能以后,就不可以再修改此函数,避免下面一系列的调用产生错误。
因此产生了装饰器
2.装饰器形成过程
我们来模拟一个发明汽车的过程。首先封装了一个汽车,汽车可以跑起来就是已经封装好的功能函数
按照开放封闭思想,此函数不能再修改,且调用是 car()直接调用
def car(): print('小汽车跑起来') car()
社会进步了,某天人们不满足现状,想计算一下汽车跑一段路程的时间,然后想增加了计时功能。
那么怎么将这个计时功能加入到汽车里面呢?
def car_time(fun): start = time.time() fun() stop = car_time() times = stop - start print(times)
这里用到了闭包思想,返回函数功能。
def car_time(fun): def inner(): start = time.time() fun() stop = car_time() times = stop - start print(times) return inner
最终得到了
import time def car(): time.sleep(2) print('小汽车跑起来') def car_time(fun): def inner(): start = time.time() fun() # 函数的嵌套 stop = time.time() times = stop - start print('汽车用时:',times) return inner # 返回函数内存地址给car_time car = car_time(car) #为了让原来的函数原封不动 car()
小汽车跑起来
汽车用时: 2.0002264976501465
上面函数是不是看起来舒服多了,我们在不动原函数的基础上加入了计时功能。
语法糖
语法糖是啥呢,所有用户执行计时功能时,不能都 加 car = car_time(car) 这个赋值吧,要不被人骂死
然后产生了语法糖,用了美滋滋,就可以省去函数赋值这一步了
import time def car_time(fun): def inner(): start = time.time() fun() stop = time.time() times = stop - start print('汽车用时:',times) return inner @car_time # 没错这个就是语法糖,@装饰器函数名 def car(): time.sleep(2) print('小汽车跑起来') car()
带参数的装饰器
总所周知函数是可以传参数的,那么装饰器装饰的函数怎么传参数呢
import time def car_time(fun): # 此处的fun = car def inner(a): start = time.time() ret = fun(a) # 参数需要fun(a)执行,这里用ret接收car的返回值 stop = time.time() times = stop - start print('汽车用时:',times) return ret # 此处将返回值返回 return inner @car_time def car(a): time.sleep(2) print('小汽车跑起来',a) car('hello') # 分析可知道。这个car = cat_time(car), car()其实是调用inner函数
小汽车跑起来 hello
汽车用时: 2.000110387802124
上述是加一个参数的函数,如果我们想加多个,甚至是列表,接受指定键值对呢。所以产生了默认的
装饰器公式
def car_time(fun): # 装饰器函数,fun是被装饰的函数 def inner(*args,**kwargs): # 接受传进来的任意参数
pass # 被装饰函数之前要做的事 ret = fun(*args,**kwargs) # 执行 装饰函数 + 参数
pass # 被装饰函数之后要做的事 return ret return inner # @car_time def car(): # 此处传参 pass
car = car_time(car) car() # 此处传参