Python 为什么decorator中的递归函数调用其内部函数
为什么在第4行递归Python 为什么decorator中的递归函数调用其内部函数,python,python-3.x,recursion,closures,decorator,Python,Python 3.x,Recursion,Closures,Decorator,为什么在第4行递归func(n)调用internal函数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 __nam
func(n)
调用internal
函数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)
第行fact=log(fact)
decoratorlog
返回对内部
函数对象的引用。此引用被分配给namefact
和fact.\uuuu name\uuuu
现在打印内部
。另外,当我检查id(fact)
时,它会返回新值
内部装饰的fact
函数自由变量func
仍然指向原始fact
函数对象。我可以通过使用id(func)
或func.\uuuu name\uuuu
insideinside
来确定它,它与之前一样。那部分我就是不明白。当递归函数在result=func(n)
insideinner
行中运行时,func(n)
调用的fact
(或inner
)不是原始的fact
。这让我很困惑,因为func
仍然指向原始的事实
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)
为什么decorator内部的递归函数调用其内部函数,而不是原始函数,该函数已传递给decorator,并且仍然引用它?正如@khelwood已经解释的internal()
被打印4次,因为递归调用内部函数4次,很容易
您的fact
函数在internal
函数内的result=func(n)
行中被调用。如果您打印(事实名称)
输出为内部
,因为事实
是内部
功能
这可能会让人困惑,因为您在log
decorator中传递的每个函数都将成为内部
函数。
为了避免这种混淆,我建议像这样使用wrapps
decorator:
from functools import wraps
def log(func):
@wraps(func)
def inner(n):
print('inner()')
result = func(n)
return result
return inner
这样,您在装饰器内部传递的func
将保持原始身份,并且打印(事实.\uuuu姓名.\uuuuuuuuu)
将打印事实内部
替换事实
。对事实
的任何递归调用都是对内部
的调用。它实际上调用了这两个函数,但事实
在内部
调用中被调用。如果我调用func.\uuu name\uuuu
或id(func)
内部
,它将打印事实
,并且仍然引用原始函数。那么为什么func(n)
调用internal
?因为fact
既是函数名也是变量名。你不应该这样做,因为这让人困惑。当您写入fact
时,它引用的是变量,而不是函数,并且由于变量fact
的值是log(fact)
因此调用log
函数并返回internal
。因此,使用类似于logging\u fact
的方法更改变量的名称会更清晰。@edzoons基本上你的log()
所做的就是返回一个internal
func,你分配给log()
的任何变量都将是一个内部函数。你覆盖了事实
名称,这是不应该做的。我终于明白了,你们俩(@JLeno46和@khelwood)想对我说的话。原始的fact
函数加载全局名称fact
,顺便说一句,它是修饰的fact
。谢谢。@khelwood如果我将名称fact
更改为logging\u 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)