为什么装饰器中的递归函数调用其内部函数

Why recursive function in decorator calls its inner function

为什么在第 4 行递归 func(n) 调用 inner 函数 n 次,而不仅仅是原始函数 fact.

def log(func):
    def inner(n):
        print('inner()')
        result = func(n)
        return result
    return inner

def fact(n):
    return 1 if n < 2 else n*fact(n-1)

fact = log(fact)

if __name__ == '__main__':
    fact(4)

输出令我困惑的内容(预期只打印一次 运行):

inner()
inner()
inner()
inner()

fact = log(fact) 装饰器 log returns 引用 inner 函数对象。此引用已分配给名称 factfact.__name__ 现在打印 inner。另外,当我检查 id(fact) 它 returns 新值时。

内部修饰的fact函数自由变量func仍然指向原来的fact函数对象。我可以通过在 inner 中使用 id(func)func.__name__ 来确定它,它与装饰之前相同。而我只是不明白的部分。当递归函数 运行s in line result = func(n) inside inner, func(n) calls decorated fact(or inner) not original fact .这让我很困惑,因为 func 仍然指向原来的 fact.

为什么装饰器内部的递归函数调用它的内部函数,而不是传递给装饰器并仍然引用它的原始函数?

正如@khelwood 已经解释的那样,inner() 被打印了 4 次,因为递归调用了 inner 函数 4 次,很简单。

您的 fact 函数在此行 result = func(n) inner 函数中被调用。如果你 print(fact.__name__) 输出是 inner,因为 fact inner 函数。

这可能会让人感到困惑,因为您在 log 装饰器中传递的每个函数都将成为 inner 函数。 为了避免这种混淆,我建议像这样使用 wraps 装饰器:

from functools import wraps
def log(func):

    @wraps(func)
    def inner(n):
        print('inner()')
        result = func(n)
        return result
    return inner

这样,您在装饰器中传递的 func 将保持原始身份,并且 print(fact.__name__) 将打印 fact.