Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 函数的递归版本在修饰时失败_Python - Fatal编程技术网

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之后执行