Python 函数的递归版本在修饰时失败
我有以下代码,由于某种原因,被修饰函数的递归版本失败,出现以下异常Python 函数的递归版本在修饰时失败,python,Python,我有以下代码,由于某种原因,被修饰函数的递归版本失败,出现以下异常 TypeError:不支持*:'int'和'NoneType'的操作数类型 这是我的密码 def deco_func(f): def wrapper(*args): print('Decorating') res = f(*args) print(res) print('Done !!') return wrapper @deco_func de
TypeError:不支持*:'int'和'NoneType'的操作数类型
这是我的密码
def deco_func(f):
def wrapper(*args):
print('Decorating')
res = f(*args)
print(res)
print('Done !!')
return wrapper
@deco_func
def fact(n):
# res = 1
# for i in range(n, 0, -1):
# res = res * i
#return res
if n > 0:
return n * fact(n-1)
else:
return 1
fact(5)
观察到的另一件事是,每次调用函数f
时,语句print('Decorating')
也在运行
这让我抓狂,我在这里迷路了,因为一旦函数事实
被修饰,它就会得到包装器对象的值
,当我们调用事实(6)
时,它实际上在调用包装器(6)
,在它的主体wrapper
函数调用函数对象f
,这实际上是原始的fact
,令人困惑的部分是对f(*args)
的调用如何以及为什么将控件发送回wrapper
函数,以及为什么每次都打印打印语句,因为f
来自封闭范围,并且应该保留它的值,因为python为它创建了一个闭包
第二件事,我试着调试代码,一旦n的值达到0,它将值1返回到res
,然后突然n
再次变为1,并在下面一行抛出异常
返回n*事实(n-1)
谁能解释一下这里到底发生了什么,我在概念上遗漏了什么 将返回(res)
添加到包装器函数中。任何未能执行return
语句的python函数都会隐式返回None
执行调用时:
return n * fact(n-1)
这是,凭借你的装饰师,真的:
return n * wrapper(n-1)
但是,由于wrapper()
返回None
语句如下:
return n * None
因此,您的错误消息:
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
这是你的装饰师,修好了
def deco_func(f):
def wrapper(*args):
print('Decorating')
res = f(*args)
print(res)
print('Done !!')
return res # <--- ADD THIS LINE
return wrapper
def deco_func(f):
def包装(*args):
打印(‘装饰’)
res=f(*args)
打印(res)
打印('Done!!')
return res#感谢您指出这一点,但我仍然不明白它为什么要调用包装器函数,因为它不应该只记住来自封闭范围的事实。正因为如此,print语句每次都在运行,它再次调用包装函数,因为您实现了一个递归算法。请注意,fact()
递归调用fact()
。由于fact()
是修饰的,每个递归调用都会调用wrapper.call to f(*args)调用fact()并在事实内部调用wrapper(n-1),现在我不明白为什么return会在这里创建一个prob,wrapper控件中的bcoz永远不会超过res=f(*args),因此像f(0)这样的最终调用会导致res=5*4*3*2*1,一旦计算了res,控件就应该转到下一个语句。所以我不明白为什么在包装器中没有return语句会产生问题,因为return只会在计算了res之后执行,您好,请您详细解释一下,在过去的两天里,我一直在努力去理解,但是我不能。。。。我非常感谢您在这里的帮助和支持。调用f(*args)调用fact()并在它调用包装器(n-1)的事实中,现在我不明白为什么return在这里创建一个prob,包装器控件中的bcoz永远不会超出res=f(*args),因此像f(0)这样的最后一个调用将导致res=5*4*3*2*1,一旦计算了res,控件就应该转到下一个语句。所以我不明白为什么在包装器中没有return语句会产生问题,因为return只会在计算了res之后执行