为什么装饰器中的递归函数调用其内部函数
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
函数对象。此引用已分配给名称 fact
,fact.__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
.
为什么在第 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
函数对象。此引用已分配给名称 fact
,fact.__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
.