1.什么是装饰器
让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
装饰器装饰一个函数,带一个或者多个参数的函数,带返回值的函数
2.装饰器的形成过程
def func1():print('in func1')def timer(func):def inner():start = time.time() # time.time() 1970年后经过的浮点秒数func()print(time.time() - start)return innerfunc1 = timer(func1)func1()
@ 语法糖
def timer(func): #func1def inner():start = time.time()time.sleep(2)func()print(time.time()-start)return inner@timer # func1 = timer(func1)def func1():print('in func1')###就是每次还得传个值这样就比较麻烦 #innerfunc1() #>>>inner()
3.
3.1带一个参数的装饰器函数
import timedef timer(func):def inner(a):start = time.time()func(a)print(time.time() - start)return inner@timerdef func1(a):time.sleep(1)print(a)func1('hello world')
3.2装饰一个带各种参数的函数
import timedef timer(func):def inner(*args,**kwargs):start = time.time()func(args,kwargs)print(time.time() - start)return inner@timerdef func1(*args,**kwargs):print(args,kwargs)func1('hello world','abc',123,432)
3.3装饰带返回值的函数
def timer(func):def inner():start = time.time()time.sleep(0.5)ret = func()print(time.time() - start)return retreturn inner@timer #==> func1 = timer(func1)def func1():print('in func1')return '我是返回值'ret = func1()print(ret)
3.4查看函数的相关信息,在加上装饰器后就失效了
def index():'''这是一条注释信息'''print('from index')print(index.__doc__) # 查看函数注释print(index.__name__) # 查看函数字符串名称但是此处如果我想看一个被装饰器装饰的函数的字符串函数名就会显示的是inner的名字print(func1.__name__)
3.5导入wraps装饰器
from functools import wrapsdef deco(func):@wraps(func)def wrapper(*args,**kwargs):return func(*args,**kwargs)return wrapper@decodef index():'''这是一条注释信息'''print('from index')print(index.__doc__) # 查看函数注释print(index.__name__) # 查看函数名称
4.开放封闭原则
对扩展时开放的,对修改是封闭的 封版之后不允许修改了
软件实体应该是可扩展但是不可修改的。
- 对于扩展是开放的
- 对于修改是封闭的
装饰器完美的遵循了这个开放封闭原则
5.装饰器的固定结构
from functools import wrapsdef timer(func):@wraps(func)def inner (*args,**kwargs) #被装饰函数里面肯定会传的参数'''执行函数之前要做的'''re = func(*args,**kwargs) #使我们被装饰函数'''执行函数之后要做的'''return rereturn inner# 下面是加上wraps的固定结构from functools import wrapsdef timer(func):@wraps(func)def wrapper(*args,**kwargs)return func(*args,**kwargs)return wrapper
6.带参数的装饰器
加上一个outer函数,可以携带一个flag的值,然后控制装饰器是否生效
def outer(flag):def timer(func):def inner(*args,**kwargs):if flag:print('函数开始执行')re = func(*args,**kwargs)print('函数执行完毕')else:re = func(*args, **kwargs)return rereturn innerreturn timer#@timeer #timer =outer(true)@outer(True)def func():print('test'/)func()
7.多个装饰器装饰一个函数
def wrapper1(func):def inner1():print('第一个装饰器,在程序运行之前')func()print('第一个装饰器,在程序运行之后')return inner1def wrapper2(func):def inner2():print('第二个装饰器,在程序运行之前')func()print('第二个装饰器,在程序运行之后')return inner2@wrapper1@wrapper2def f():print('Hello')f()
