代码之家  ›  专栏  ›  技术社区  ›  Matt

双重装饰,为什么我的一个封闭函数没有被执行?

  •  1
  • Matt  · 技术社区  · 7 年前

    我试图理解如何在一个函数上使用两个decorator,代码如下:

    def fxn(func):
        print("fxn_outer 1")
        def fxn_inner(*args, **kwargs):
            print("fxn_inner 1")
        return fxn_inner
    
    def fxn2(func):
        print("fxn_outer 2")
        def fxn_inner2(*args, **kwargs):
            print("fxn_inner 2")
        return fxn_inner2
    
    @fxn
    @fxn2
    def fxn3 (a, b):
        print(a + b)
    
    fxn3(1, 2)
    

    fxn_inner 在上面的代码中执行,但是 fxn_inner2 不是。

    输出为:

    fxn_outer 2
    fxn_outer 1
    fxn_inner 1
    

    当我期望以下输出时:

    fxn_outer 2
    fxn_outer 1
    fxn_inner 1
    fxn_inner 2
    

    2 回复  |  直到 7 年前
        1
  •  4
  •   Giacomo Alzetta    7 年前

    decorator只是调用函数和重新分配名称的语法糖,因此您所做的工作等效于:

    fxn3 = fxn2(fxn3)
    fxn3 = fxn(fxn3)
    
    fxn3(1, 2)
    

    发生了什么?第一次任务完成后 fxn3 == fxn2_inner . 在第二行之后 fxn3 == fxn_inner .

    但是 fxn fxn_inner )他们只是扔掉了参数 func ! 因此,当你打电话时,你看不到它被呼叫 fxn3(1,2) == fxn_inner(1, 2)

    如果要调用原始函数,应该调用 内部 *_inner 功能:

    def fxn(func):
        print("fxn_outer 1")
        def fxn_inner(*args, **kwargs):
            print("fxn_inner 1")
            return func(*args, **kwargs)
        return fxn_inner
    
    def fxn2(func):
        print("fxn_outer 2")
        def fxn_inner2(*args, **kwargs):
            print("fxn_inner 2")
            return func(*args, **kwargs)
        return fxn_inner2
    
        2
  •  1
  •   Léopold Houdin    7 年前

    这是因为您没有在decorator的主体中执行给定给decorator的函数(包装函数)。因此,执行在第一个装饰器的主体中停止(即。 fxn_inner

    通常,您对decorator所做的是调用(调用)decorator中的decorated函数,即。

    def fxn(func):
        print("fxn_outer 1")
        def fxn_inner(*args, **kwargs):
            print("fxn_inner 1")
            func(*args, **kwargs)
        return fxn_inner
    
    def fxn2(func):
        print("fxn_outer 2")
        def fxn_inner2(*args, **kwargs):
            print("fxn_inner 2")
            func(*args, **kwargs)
        return fxn_inner2
    
    @fxn
    @fxn2
    def fxn3 (a, b):
        print(a + b)
    
    fxn3(1, 2)