装饰器自动调用

Decorator Invoked Automatically

我试图理解脚本的两个版本背后的逻辑,其中使用了装饰器。在其中一个脚本中,装饰器被自动调用,甚至没有被调用。

脚本 1:

def outer_decorator(input_function):
    def decorator(*args, **kwargs):
        print "Outer Decorator Called"
        output = input_function(*args, **kwargs)
        return output

    return decorator


class X:

    @outer_decorator
    def inner_decorator(input_function):
        def decorator(*args, **kwargs):
            output = input_function(*args, **kwargs)
            print "Inner Decorator Called"
            return output

        return decorator


    def z(self, a, b):
        """
        Function returns a - b
        """
        return a - b


x = X()
print(x.z(1, 2))

输出

-1

所以每当我 运行 脚本 1 时,我都会创建一个 class X 的对象,然后调用函数 z。因此,在这种情况下,内部装饰器函数未在任何地方使用,因此未被调用。

脚本 2:

def outer_decorator(input_function):
    def decorator(*args, **kwargs):
        print "Outer Decorator Called"
        output = input_function(*args, **kwargs)
        return output

    return decorator


class X:

    @outer_decorator
    def inner_decorator(input_function):
        def decorator(*args, **kwargs):
            output = input_function(*args, **kwargs)
            print "Inner Decorator Called"
            return output

        return decorator

    @inner_decorator
    def s(self, a, b):
        """
        Function return a + b
        """
        return a + b

    def z(self, a, b):
        """
        Function returns a - b
        """
        return a - b


x = X()
print(x.z(1, 2))

所以现在在上面的脚本中我介绍了另一个使用 @inner_decoratorfunction s。但我仍然只调用 class xfunction z。但是当我 运行 这个脚本时,我得到以下输出。

Outer Decorator Called
-1

那么为什么@outer_decorator被调用并打印了?
是不是因为某处使用的装饰器被解释器处理了?

调用 outer_decorator 的原因是您正在装饰装饰器本身。

def outer_decorator(input_function):
    def decorator(*args, **kwargs):
        print "Outer Decorator Called"
        output = input_function(*args, **kwargs)
        return output

    return decorator


class X:

    @outer_decorator
    def inner_decorator(input_function):
        def decorator(*args, **kwargs):
            output = input_function(*args, **kwargs)
            print "Inner Decorator Called"
            return output

        return decorator

这个表达式 @outer_decorator 实际上转换为 inner_decorator = outer_decorator(inner_decorator),所以在你的代码中虽然你没有明确调用你用 inner_decorator 装饰的函数但是当你装饰 function sinner_decorator 它实际上调用了 inner_decorated 的修饰版本,后者又调用了 outer_decorator.

中定义的 decorator 函数

我希望这能让事情变得清晰。

脚本 1:

inner_decorator = outer_decorator(inner_decorator) # i.e. a function 
# object, no invocation

脚本 2: 这里:

@outer_decorator
    def inner_decorator(input_function):

这被调用:

inner_decorator = outer_decorator(inner_decorator) # i.e. a function 
# object, no invocation

但是, 这里:

@inner_decorator
    def s(self, a, b):

这导致:

s = inner_decorator(s) = outer_decorator(inner_decorator)(s) # causes 
# invocation of outer_decorator