欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

[python]装饰器 decorator @yntactic sugar 装饰器的本质

最编程 2024-06-10 15:25:54
...

装饰器本质

python的装饰器本质上是一个语法糖,本质的意义在于将一个函数以参数的形式传入另一个函数,并且返回一个新的函数的过程。 可能有点难理解,但是一个例子你就会懂


# 这是一个非常简单装饰器
def decorator(func):
    def inner(*args, **kwargs):
        print("run decorator")
        return func(*args, **kwargs)
    return inner

上面的代码定义了一个简单的装饰器,语法糖的调用方式如下

@decorator
def test():
    print("run test")

test()

不使用语法糖调用,代码如下:

def test():
    print("run test")

test = decorator(test)  # 将函数test传入装饰器,并返回一个新的函数
test()  调用结果和上面一模一样

带参数的装饰器

带参数的装饰器本质是还是和简单的装饰器一样

def decorator_num(num):
    def decorator(func):
        def inner(*args, **kwargs):
            print(num)
            return func(*args, **kwargs)
        return inner
    return decorator

@decorator_num(2)  # 注意这里是加了括号,所以会先调用将返回的结果在作为装饰器
def test():
    print("test")

test()

上面的调用方法等效于

def test():
    print("test")

test = decorator_num(2)(test)

test()

使用装饰器需要注意的地方

  • 对于带参数的装饰器是不可以在inner函数中修改参数的值,只能读取,看下面例子
def decorator_num(num):
    def decorator(func):
        def inner(*args, **kwargs):
            num += 1   # 如果我修改num的值,那么会直接报错
            print(num)
            return func(*args, **kwargs)
        return inner
    return decorator

@decorator_num(2)
def test():
    print("test")

test()
  • 对于多个装饰器的执行顺序,包装的时候,从下往上,所以执行的时候,就是从上往下,看下面例子
def decorator_1(func):
    def inner(*args, **kwargs):
        print("decorator_1")
        return func(*args, **kwargs)
    return inner


def decorator_2(func):
    def inner(*args, **kwargs):
        print("decorator_2")
        return func(*args, **kwargs)
    return inner


@decorator_2
@decorator_1
def test():
    print("test")


test()
# 打印结果
# decorator_2
# decorator_1
# test

把上面的调用方式修改一下你就更容易理解了

def test():
    print("test")


test = decorator_2(decorator_1(test))
test()  # 打印结果与上面一致,因为本质都是一样的
  • 由于装饰器会返回一个新的函数,所以原本函数的一些元数据会被更改,这个解决也简单,给所有的inner方法在加一个装饰器即可 如下
from functools import wraps


def decorator_1(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print("decorator_1")
        return func(*args, **kwargs)
    return inner

类装饰器

类装饰器分为两种,第一种是作用在类上面的装饰器,也就是给类使用的,第二种是装饰器本身就是类。

作用在类上面的装饰器

def decorator(func):
    def inner(*args, **kwargs):
        print("decorator")
        return func(*args, **kwargs)

    return inner

@decorator
class A:
    pass

A = decorator(A)()  # 和上面的写法完全一样

装饰器本身就是类

class Decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('decorator')
        return self.func(*args, **kwargs)


@Decorator
def a():
    print('a')

a = Decorator(a)()  # 和上面的写法完全一样