递归函数装饰器报错排查:斐波那契函数出现NoneType加法错误
递归函数计时装饰器的错误分析与修复
问题核心原因
- 装饰后的
fibonacci实际指向time_calculator里的n_th_number函数,这个函数没有return语句,默认返回None。 - 递归执行
fibonacci(n-1)+fibonacci(n-2)时,相当于尝试将两个None相加,直接触发TypeError。 - 额外问题:原装饰器会对每一次递归调用都执行计时打印,产生大量冗余输出,不符合统计整个递归过程总耗时的需求。
修复方案
方案1:让装饰器返回原函数结果(解决错误,但保留每层递归计时)
修改装饰器的嵌套函数,保存原函数执行结果并返回,供递归调用使用:
import time def time_calculator(func): def n_th_number(n): start = time.time() result = func(n) # 保存原函数的计算结果 end = time.time() print(f'fibonacci({n}) 耗时: {end - start} 秒') return result # 返回结果,支持递归的加法运算 return n_th_number @time_calculator def fibonacci(n): if n==0 or n==1: return n else: return fibonacci(n-1)+fibonacci(n-2) # 调用并打印最终结果 print(fibonacci(30))
方案2:仅统计整个递归的总耗时(推荐)
如果只需要统计fibonacci(30)的整体耗时,避免每层递归重复计时,可选择以下两种方式:
方式A:外层封装计时(简单直接)
import time def fibonacci(n): if n==0 or n==1: return n else: return fibonacci(n-1)+fibonacci(n-2) def time_calculator(func, *args): start = time.time() result = func(*args) end = time.time() print(f'fibonacci 总耗时: {end - start} 秒') return result # 调用方式 final_result = time_calculator(fibonacci, 30) print(final_result)
方式B:改进装饰器,仅最外层计时
利用functools.wraps保留原函数标识,添加递归标志位避免重复计时:
import time from functools import wraps def time_calculator(func): @wraps(func) def wrapper(n): # 仅在第一次调用时执行计时逻辑 if not hasattr(wrapper, '_is_recursing'): wrapper._is_recursing = True start = time.time() result = func(n) end = time.time() print(f'fibonacci 总耗时: {end - start} 秒') delattr(wrapper, '_is_recursing') return result # 递归调用时直接执行原函数 return func(n) return wrapper @time_calculator def fibonacci(n): if n==0 or n==1: return n else: return fibonacci(n-1)+fibonacci(n-2) print(fibonacci(30))
内容的提问来源于stack exchange,提问作者user23666587
相关产品推荐
相关产品推荐

