Python(必学高级知识)——装饰器(一文搞懂)

Python——装饰器

一,定义

python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。一般而言,我们要想拓展原来函数代码,最直接的办法就是侵入代码里面修改。例如:

二,实现

原始函数:

import time
def func():
    print("hello")
    time.sleep(1)
    print("world")

将函数作为参数传递的函数:

#避免直接侵入原函数修改,但是生效需要再次执行函数
import time

def deco(func):
    startTime = time.time()
    func()
    endTime = time.time()
    msecs = (endTime - startTime)*1000
    print("time is %d ms" %msecs)


def func():
    print("hello")
    time.sleep(1)
    print("world")

if __name__ == '__main__':
    f = func
    deco(f)#只有把func()或者f()作为参数执行,新加入功能才会生效
    print("f.__name__ is",f.__name__)#f的name就是func

这里我们定义了一个函数deco,它的参数是一个函数,然后给这个函数嵌入了计时功能。这样我们也顺利的扩展了我们的原函数func,但是,如果遇到上千上万个原函数,我们在对这上千上万个函数扩展时,难道也是一个一个作为参数传递,再一个一个执行吗?所以我们接下来引入了装饰器来解决这个问题

先上代码:

#既不需要侵入,也不需要函数重复执行
import time

def deco(func):
    def wrapper():
        startTime = time.time()
        func()
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func():
    print("hello")
    time.sleep(1)
    print("world")

if __name__ == '__main__':
    f = func #这里f被赋值为func,执行f()就是执行func()
    f()

这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数func()前面加上@deco,func()函数就相当于被注入了计时功能,现在只要调用func(),它就已经变身为“新的功能更多”的函数了。
所以这里装饰器就像一个注入符号:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。

#带有参数的装饰器

#带有参数的装饰器
import time

def deco(func):
    def wrapper(a,b):
        startTime = time.time()
        func(a,b)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

if __name__ == '__main__':
    f = func
    f(3,4)
    #func()

#带有不定参数的装饰器

#带有不定参数的装饰器
import time

def deco(func):
    def wrapper(*args, **kwargs):
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
    return wrapper


@deco
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))

@deco
def func2(a,b,c):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b+c))


if __name__ == '__main__':
    f = func
    func2(3,4,5)
    f(3,4)
    #func()

多个装饰器

#多个装饰器

def dec1(func):
    print("1111")
    print("dec1正在执行")

    def one():
        print("2222")
        func()
        print("3333")

    return one


def dec2(func):
    print("aaaa")
    print("dec2正在执行")
    
    def two():
        print("bbbb")
        func()
        print("cccc")

    return two


@dec1
@dec2
def test():
    print("test test")


if __name__ == '__main__':
    test()


'''
结果:
aaaa
dec2正在执行
1111
dec1正在执行
2222
bbbb
test test
cccc
3333


'''

多个装饰器执行的顺序:

  1. 执行最后一个装饰器返回指定函数之前(这里是two函数)的代码,就比如这里先返回 aaa,dec2正在执行
  2. 再向上执行另一个装饰器,若该装饰器是第一个装饰器,则执行该装饰器中调用原函数(这里是text函数)之前的所有代码,若该装饰器不是第一个,则执行代码和1步骤中类似,直到执行为第一个装饰器。
  3. 执行下一个装饰器返回函数(这里是two函数)之后到原函数(这里是text函数)之前的代码,执行完成以后像前面一样依次再执行第二个(。。。。n)代码
  4. 此时执行到最后一个装饰器函数,调用原函数(这里是text函数),再执行完该装饰器后面的函数,再像这样依次执行上一个函数(注意:text函数不重复执行)直到执行完第一个装饰器函数

执行顺序转折点有两个:第一个就是调用返回函数之前,第二个就是调用原函数之前,从最后一个装饰器开始执行,到第一个装饰器结束

装饰器的外函数和内函数之间的语句是没有装饰到目标函数上的,而是在装载装饰器时的附加操作。

小伙伴们可以加我的微信公众号 梦码城 ,接下来的日子里我会在公众号上发布各种与编程方面的总结学习知识,也会送各位小伙伴大量的学习资源,梦码城,期待你的加入
文章不易,小伙伴们点个赞加个关注鼓励下梦码呗,梦码会继续努力的

猜你喜欢

转载自blog.csdn.net/qq_45724216/article/details/106440404