装饰器的作用
- 装饰器本质上是一个高级Python函数,通过给别的函数添加@标识的形式实现对函数的装饰
2.装饰器的功能:
- 它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
- 它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。
- 装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
def fn(f1): #python是解释性语言,当他解释道@fn时会执行此函数,执行到def事定义一个函数,并不执行他,最后执行return将创建的内层函数返回
def fc():
print("这里开始对f1函数权限进行验证")
f1()
print("f1函数已经处理完毕了")
return fc
@fn #这个@fn标识符效果等同于f1=fn(f1)。
def f1():
print("这里f1函数的功能展示")
因为@fn的效果等同于f1=fn(f1),所以直接调用f1()相当于实现了fn(f1)(),进而达到原来的效果。可以在不修改源代码的情况下为代码添加功能。
f1() # 直接执行
结果如下:
这里开始对f1函数进行权限验证
这里f1函数的功能展示
f1函数已经处理完毕了
多层装饰器
# 定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
# 定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@makeBold # 外层装饰(执行的时候先执行外层)
@makeItalic # 内层装饰(装饰的时候先装饰内层)
def test1():
return "hello world"
print(test1())
运行结果:
<b><i>hello world</i></b>
总结要点:
-
python中装饰器是随着程序的加载运行而自动加载的,跟调不调用方法没有关系.所以只要是装饰器内部函数以外的部分都会自动加载执行,不用调用。
-
所以当一个函数被多个装饰器装饰时,装饰器的加载顺序是从内到外的。其实很好理解:装饰器是给函数装饰的,所以要从靠近函数的装饰器开始从内往外加载。
-
但是执行顺序是由上到下的,及先执行
makeBold
并且makeBold
中的fn()
指向makeItalic
,然后makeItalic
中的fn()
指向test1()
被装饰的函数有参数
def timefun(func):
def wrapped_func(*args, **kwargs):
print("call")
func(*args, **kwargs) # 此处也应该使用*args接收参数,如果使用args接收的话,收到是参数是一个元组不会拆包
return wrapped_func
@timefun
def foo(a, b, c):
print(a+b+c)
foo(3,5,7)
带参数的装饰器
def strongdeco(*args, **kwargs):
def basedeco(func):
def wrapper(*args, **kwargs): # 此时返回的内层函数既有数据也有功能
if args[0] == 1: # 取出参数(对装饰器参数的使用)
print('当装饰器参数=1时,这句话是对的')
if args[0] == 0:
print('当装饰器参数=0时,这句话是错的')
print('上有天堂')
output = func(*args, **kwargs) # 此处无论被装饰的函数有无返回值都接收一下
print('下有苏杭')
return output
return wrapper
return basedeco
# 3层函数
@strongdeco(0)
def testfun(name):
'''这是一个测试'''
print(f'{name}说:我就是我,不一样的烟火')
print(testfun.__doc__)
if __name__ == '__main__':
testfun('IT')