功能的递归版本在装饰时失败

时间:2017-08-09 18:41:20

标签: python

我有以下代码,由于某种原因,递归版本正在修饰的函数失败,并带有以下异常

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)

另一件事是,每次调用函数print('Decorating')时,语句f也在运行。

这让我抓狂,我迷失在这里,因为只要功能fact被装饰,它就会获得wrapper object的值,当我们调用fact(6)时,它实际上正在调用{ {1}},进一步在其内部wrapper(6)函数正在调用函数对象wrapper,这实际上是原始的f,令人困惑的部分是对{的调用的方式和原因{ {1}}正在将控件发送回fact函数以及每次打印print语句的原因,因为f(*args)来自封闭范围,并应保留其值,因为python创建了一个闭包它

第二件事,我尝试调试代码,一旦n的值达到0,它就会将值1返回到wrapper,然后无处不在f再次变为1,它会在下面抛出异常线

res

任何人都可以请解释这里到底发生了什么,以及我在概念上究竟错过了什么!!!

1 个答案:

答案 0 :(得分:3)

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