>我有以下代码,由于某种原因,正在修饰的函数的递归版本失败,出现以下异常
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 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')
也会运行。
这让我发疯,我在这里迷路了,因为一旦函数fact
被装饰,它就会获得wrapper object
的值,当我们调用fact(6)
时,它实际上是在调用wrapper(6)
,在它的主体内部,wrapper
函数正在调用函数对象f
这实际上是原始fact
, 令人困惑的部分是调用f(*args)
如何以及为什么将控件发送回wrapper
函数,以及为什么它每次都打印 print 语句,因为事情f
来自封闭范围并且应该保留其值,因为 python 为其创建了闭包。
第二件事,我尝试调试代码,一旦 n 的值达到 0,它就会返回值 1 到res
然后突然n
再次变为 1,并在下面一行抛出异常
return n * fact(n-1)
谁能解释一下这里到底发生了什么,以及我在概念上到底错过了什么!!
将return(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