python中为其他函数添加额外功能,而不修改源代码的方式-------装饰器的使用讲解及代码示例(类似于java的装饰设计模式)
程序员文章站
2024-03-26 11:20:05
...
讲解内容及代码都在下面
#Filename:decorator.py
#场景:本身一套程序已经有了自己本身的一系列函数,但是,现在这些函数的功能有限,
#想要增加一些额外的功能,但是,如果要是修改原代码的话,可能会产生一系列的连带
#错误,所以,就产生了装饰器的概念。
#装饰器:本质就是一个函数,装饰其他的函数,为其他的函数添加附加的功能。
#原则:不修改被装饰函数的原代码以及调用方式,类似于java的装饰设计模式
#要想学会装饰器必须先知道两个概念,一个是高阶函数,另一个是嵌套函数
#高阶函数:把一个函数名作为实参传递给另一个函数,返回值是函数名
#嵌套函数:就是一个函数嵌套一个函数,需要注意的是,嵌套必须是def嵌套def,比如
#def test:
# test()
#上面这个例子就不是嵌套函数,只是函数的调用而已
#装饰器=高阶函数+嵌套函数
#
#步骤:
#1.创建一个装饰器,也就是函数timer,把func作为参数传进去,代表任意的函数。
#2.直接在装饰器里面嵌套一个函数,由于可能传递若干个参数,也可能不传参数,
#所以我们用*args,**kwargs代替。
#3.在嵌套函数里面调用原来的老函数即func(*args,**kwargs),并写入新的逻辑。
#4.返回嵌套函数,到此为止,装饰器里面只是返回了一个函数,并没有进行调用。
#5.在原来的函数上面写上@timer,代表test1=timer(test1),这句话的意思是将原来
#的函数传到装饰器当中,返回的deco就等于了test1。
#6.调用test1(),由于deco等于test1,所以test1()就相当于deco(),也就自然
#的调用了新的和旧的逻辑。(带参数的test2同理)
#到此为止,我们也就达成了效果,不修改被装饰函数的原代码以及调用方式
import time
def timer(func): #timer(test1) func=test1
def deco(*args,**kwargs):
start_time=time.time()#获取当前的时间
func(*args,**kwargs) #run test1()
stop_time = time.time()
print("函数的运行时间为:" ,stop_time-start_time)
#获取时间差
return deco
@timer #test1=timer(test1)
def test1():
time.sleep(1)#让时间等待一秒
print('老函数1')
@timer # test2 = timer(test2) = deco test2(name) =deco(name)
def test2(name,age):
print("test2:",name,age)
test1()
test2("Rain",22)
结果:
老函数1
函数的运行时间为: 1.0200014114379883
test2: Rain 22
函数的运行时间为: 0.029999971389770508
下面的例子是装饰器的加强功能
#不用特别看懂具体的处理逻辑
#现在来思考两个问题:
#第一个:如果原来的函数有返回值该怎么办
#第二个:如果两个老函数需要加以区分该怎么办
#第一个的解决方式:这里的home()返回了内容,所以我们需要在代码中改一些,即
#res = func(*args, **kwargs) # from home
#return res
#也就是在嵌套函数调用中将老函数返回的值赋给res,再返回res
#最后再调用print(home()) #wrapper(),将它打印出来即可。
#第二个的解决方式:
#首先我们在老函数的上边的@auth(auth_type="ldap")加了一个参数,加以区分
#然后,我们在装饰类中又多加了一层
#def auth(auth_type):
# print("auth func:",auth_type)
# def outer_wrapper(func):
#第一层的参数是加以区分的内容
#第二层的参数是需要传递进来的函数
#记得要在后面同样的返回这个outer_wrapper函数
########################
import time
user,passwd = '1','2'
def auth(auth_type):
print("auth func:",auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print("wrapper func args:", *args, **kwargs)
if auth_type == "local":
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
res = func(*args, **kwargs) # from home
print("---after authenticaion ")
return res
else:
exit("\033[31;1mInvalid username or password\033[0m")
elif auth_type == "ldap":
print("搞毛线ldap,不会。。。。")
return wrapper
return outer_wrapper
def index():
print("welcome to index page")
@auth(auth_type="local") # home = wrapper()
def home():
print("welcome to home page")
return "from home"
@auth(auth_type="ldap")
def bbs():
print("welcome to bbs page")
index()
print(home()) #wrapper()
bbs()
结果:
auth func: local
auth func: ldap
welcome to index page
wrapper func args:
Username:1
Password:2
[32;1mUser has passed authentication[0m
welcome to home page
---after authenticaion
from home
wrapper func args:
搞毛线ldap,不会。。。。
上一篇: 代码重构经验总结 博客分类: 代码架构 设计模式框架CC++C#
下一篇: 构造函数模式