装饰器
一、介绍:
装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就不能大批量的修改源代码,这样是不科学的也是不现实的,因此就产生了装饰器,使得其满足:
不能修改被装饰的函数的源代码
不能修改被装饰的函数的调用方式
满足1、2的情况下给程序增添功能
那么根据需求,同时满足了这三点原则,这才是我们的目的。因为,下面我们从解决这三点原则入手来理解装饰器。
1、先明白这段代码


2、需求来了
初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需调用基础平台提供的功能即可。如下:


def w1(func):
def inner():
print('正在验证权限---')
func()
return inner
def f1():
print('---f1---')
@w1 #等价于f2=w1(f2)
def f2():
print('---f2---')
f1=w1(f1)
f1()
f2()
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
正在验证权限---
---f1---
正在验证权限---
---f2---
Process finished with exit code 0
3、多个装饰器
"""多个装饰器"""
#定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
return '<b>' + fn() +'</b>'
return wrapped
def makeItalic(fn):
def wrapped():
return '<i>' + fn() +'</i>'
return wrapped
@makeBold
def test1():
return 'hello world-1'
@makeItalic
def test2():
return 'hello world-2'
@makeBold
@makeItalic
def test3():
return 'hello world-3'
print(test1())
print(test2())
print(test3())
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
<b>hello world-1</b>
<i>hello world-2</i>
<b><i>hello world-3</i></b>
Process finished with exit code 0
当Python解释器执行到@makeBold语句时,会判断下面语句是不是一个函数,如果是函数就开始装饰,如果不是则不进行装饰。因为@makeBold语句后面是@makeItalic,则@makeItalic会去判断下面的语句是不是一个函数,如果是函数就开始进行装饰。所以当包含多个装饰器时,会先用后面的装饰器进行装饰
4、装饰器什么时候进行装饰:
"""装饰器什么时候进行装饰"""
def w1(func):
print('---正在装饰1---')
def inner():
print('正在验证权限1')
func()
return inner
def w2(func):
print('---正在装饰2---')
def inner():
print('正在验证权限2')
func()
return inner
#只要Python解释器执行到了这个代码,那么就会自动的进行装饰,而不是等到调用的时候才装饰
@w1
@w2
def f1():
print('---f1---')
#在调用f1之前,已经进行了装饰
f1()
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
---正在装饰2---
---正在装饰1---
正在验证权限1
正在验证权限2
---f1---
Process finished with exit code 0
5. 装饰器示例
例1:无参数的函数
"""例1:无参数的函数"""
def func(functionName):
print('---func---1---')
def func_in():
print('---func_in---1')
functionName()
print('---func_in---2--')
print('---func---2---')
return func_in
@func
def test():
print('---test---')
test()
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
---func---1---
---func---2---
---func_in---1
---test---
---func_in---2--
Process finished with exit code 0
例2:被装饰的函数有参数
def func(functionName):
print('---func---1---')
def func_in(a,b):#如果a,b没有定义,那么会导致test(11,22)行的调用失败
print('---func_in---1')
functionName(a,b)#如果没有把a,b当做实参进行传递,那么会导致调用test()函数失败
print('---func_in---2--')
print('---func---2---')
return func_in
@func
def test(a,b):
print('---test-a=%d,b=%d---'%(a,b))
test(11,22)
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
---func---1---
---func---2---
---func_in---1
---test-a=11,b=22---
---func_in---2--
Process finished with exit code 0
例3:被装饰的函数有不定长参数
"""例3:被装饰的函数有不定长参数"""
def func(functionName):
print('---func---1---')
def func_in(*args,**kwargs):#采用不定长参数的方式满足所有函数需要参数以及不需要参数的情况
print('---func_in---1')
functionName(*args,**kwargs)#这个地方,需要写*以及**,如果不写的话,那么args是元组,而kwargs是字典
print('---func_in---2--')
print('---func---2---')
return func_in
@func
def test(a,b,c):
print('---test-a=%d,b=%d,c=%d---'%(a,b,c))
def test2(a,b,c,d):
print('---test-a=%d,b=%d,c=%d,d=%d---' % (a, b, c,d))
test(11,22,33)
test2(44,55,66,77)
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
---func---1---
---func---2---
---func_in---1
---test-a=11,b=22,c=33---
---func_in---2--
---test-a=44,b=55,c=66,d=77---
Process finished with exit code 0
例4:装饰器中的return
def func(functionName):
print("---func---1---")
def func_in():
print("---func_in---1---")
ret = functionName() # 保存返回来的haha
print("---func_in---2---")
return ret # 把haha返回到ret = test()行处的调用
print("---func---2---")
return func_in
@func
def test():
print("----test----")
return "haha"
ret = test()
print("test return value is %s" % ret)
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
---func---1---
---func---2---
---func_in---1---
----test----
---func_in---2---
test return value is haha
Process finished with exit code 0
例5:通用装饰器
def func(functionName):
def func_in(*args, **kwargs):
print("-----记录日志-----")
ret = functionName(*args, **kwargs)
return ret
return func_in
@func
def test():
print("----test----")
return "haha"
@func
def test2():
print("----test2---")
@func
def test3(a):
print("-----test3--a=%d--"%a)
ret = test()
print("test return value is %s"%ret)
a = test2()
print("test2 return value is %s"%a)
test3(11)
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
-----记录日志-----
----test----
test return value is haha
-----记录日志-----
----test2---
test2 return value is None
-----记录日志-----
-----test3--a=11--
Process finished with exit code 0
例6、带有参数的装饰器
def func_arg(arg):
def func(functionName):
def func_in():
print("---记录日志-arg=%s--" % arg)
if arg == "heihei":
functionName()
functionName()
else:
functionName()
return func_in
return func
# 1. 先执行func_arg("heihei")函数,这个函数return 的结果是func这个函数的引用
# 2. @func
# 3. 使用@func对test进行装饰
@func_arg("heihei")
def test():
print("--test--")
# 带有参数的装饰器,能够起到在运行时,有不同的功能
@func_arg("haha")
def test2():
print("--test2--")
test()
test2()
结果:
D:\Anaconda\python.exe E:/pythonwork/黑马/面向对象进阶之装饰器.py
---记录日志-arg=heihei--
--test--
--test--
---记录日志-arg=haha--
--test2--
Process finished with exit code 0
本文深入探讨了Python装饰器的概念,解析其如何在不修改原函数代码和调用方式的前提下增添功能,通过多个实例展示了装饰器的应用场景,包括权限验证、日志记录及参数处理。
1591

被折叠的 条评论
为什么被折叠?



