python装饰器,以及装饰器执行顺序

267 阅读2分钟

这是我参与2022首次更文挑战的第2天,活动详情查看2022首次更文挑战

了解装饰器之前我们要先了解闭包,维基百科中是这样表述闭包的:

在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

简单来说就是一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。这样的一个函数我们称之为闭包。具体描述可以详看这篇文章:理解Python闭包概念

装饰器的本质也是一个闭包,只是把函数作为参数然后返回一个替代函数的特殊闭包。

简单一点理解就是:装饰器本质上也是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

装饰器的执行顺序是自下而上,采用的是就近原则。所以说先执行的是最近的一个装饰器,所以一般我们web登陆验证都放在最近的,而我会把捕捉异常放在最外面。

两个例子带你理解

from functools import wraps

def a(func):
    print('11111')
    @wraps(func)
    def wrapper(*args,**kwargs):
        print('a装饰器被执行')
        func(*args,**kwargs)
        print('a装饰器执行结束')
    return wrapper

def b(func):
    print('22222')
    @wraps(func)
    def wrapper(*args,**kwargs):
        print('b装饰器被执行')
        func(*args,**kwargs)
        print('b装饰器执行结束')
    return wrapper

@b
@a
def b():
    print('ss')


b()

在这里插入图片描述 我们看结果可以发现,函数自上而下执行,装饰器回先被执行所以我们看一看到111111和22222被打印,其次从输出的字符串我们也可以清楚的看到a装饰器是在函数执行第一个会装饰的,其次是b。我们可以根据自己的需求选择。