python中为其他函数添加额外功能,而不修改源代码的方式-------装饰器的使用讲解及代码示例(类似于java的装饰设计模式)

讲解内容及代码都在下面

#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,不会。。。。

猜你喜欢

转载自blog.csdn.net/qq_41901915/article/details/82502391