关于类装饰器初始化先后的问题

一个函数,被2个类装饰器修饰,其中一个是不带参数的类装饰器,另一个是带参数的。为什么这2个装饰器的装饰先后顺序调整了,输出结果不变(总是优先初始化带参数的类装饰器)?

#不带参数的类装饰器
class ClassNoParams:
    def __init__(self, func):
        self.func = func
        print("init ClassNoParams ...")
    def __call__(self, *args, **kwargs):
        print("begin ClassNoParams ...")
        res = self.func(*args, **kwargs)
        print("end ClassNoParams ...")
        return res

#带参数的类装饰器
class ClassHasParams:
    def __init__(self, level):
        self.level = level
        print(f"init ClassHasParams, level is {level}")
    def __call__(self, func):
        @wraps(func)
        def inner(*args, **kwargs):
            print("begin ClassHasParams ...")
            res = func(*args, **kwargs)
            print("end ClassHasParams ...")
            return res
        return inner

#调整这2个装饰器的先后顺序,结果输出都一样
@ClassNoParams
@ClassHasParams(level=7)
def classtest(name="Class", age=9, sex='F'):
    print(f"My name is {name}, sex is {sex}, {age} yeras old.")

classtest()

这个问题的根本原因在于,当一个装饰器带参数时,它会返回一个函数,而不带参数的装饰器可以直接修饰函数。

因此,当两个装饰器先后顺序调整时,输出结果不变,是因为 ClassHasParams 先于 ClassNoParams 修饰 classtest 函数。

带参数的装饰器(ClassHasParams)会返回一个函数,而不带参数的装饰器(ClassNoParams)会对返回的函数进行修饰,因此结果是不变的。