什么是装饰器
让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
装饰器的形成过程
如果我想测试某个函数的执行时间
import timedef func1():print('in func1')def timer(func):def inner():start = time.time()func()print(time.time() - start)return innerfunc1 = timer(func1)func1()
Python
Copy
但是如果有多个函数,我都想让你测试他们的执行时间,你每次是不是都得 func1 = timer(func1)? 这样还是有点麻烦,因为这些函数的函数名可能是不相同,有 func1,func2,graph, 等等,所以更简单的方法,python 给你提供了,那就是语法糖。
import timedef timer(func):def inner():start = time.time()func()print(time.time() - start)return inner@timerdef func1():time.sleep(1)print('in func1')func1()
Python
Copy
装饰一个带参数的函数
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')
Python
Copy
装饰一个带各种参数的函数
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)
Python
Copy
查看函数的相关信息,在加上装饰器后就失效了
def index():'''这是一条注释信息'''print('from index')print(index.__doc__) # 查看函数注释print(index.__name__) # 查看函数名称
Python
Copy
导入 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__) # 查看函数名称
Python
Copy
开放封闭原则
一句话,软件实体应该是可扩展但是不可修改的。
- 对于扩展是开放的
- 对于修改是封闭的
装饰器的主要功能和固定结构
def timer(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
Python
Copy
带参数的装饰器
加上一个 outer 函数,可以携带一个 flag 的值,然后控制装饰器是否生效
def outer(flag):def timer(func):def inner(*args,**kwargs):if flag:print('函数开始执行')re = func(*args,**kwargs)if flag:print('函数执行完毕')return rereturn innerreturn timer@outer(True)def func():print('test')func()
Python
Copy
多个装饰器装饰一个函数
def wrapper1(func):def inner():print('第一个装饰器,在程序运行之前')func()print('第一个装饰器,在程序运行之后')return innerdef wrapper2(func):def inner():print('第二个装饰器,在程序运行之前')func()print('第二个装饰器,在程序运行之后')return inner@wrapper1@wrapper2def f():print('Hello')f()
