递归函数装饰器报错修复:实现计算fib(5)十次运行平均耗时的装饰器
修复你的斐波那契计时装饰器问题
我来帮你排查并修复这个装饰器的问题,你的代码主要有三个关键错误需要修正:
1. HTML转义字符导致语法错误
你代码里的num < 2是HTML的小于号转义字符,Python无法识别,必须改成标准的<运算符。
2. 装饰器返回值错误
原装饰器的wrapper函数最后返回的是func(函数对象),而不是函数调用的结果func(*args, **kwargs),这会导致调用fib(5)时得到的是函数对象,而不是斐波那契数的计算结果。
3. 递归调用重复触发计时逻辑
这是最严重的问题:你的装饰器把fib替换成了wrapper,所以每次递归调用fib(num-1)时,都会执行wrapper里的10次循环,导致计算量暴增,完全偏离了“计算fib(5)运行10次的平均时间”的需求——我们需要的是整个fib(5)的调用重复10次,而不是每次递归都重复10次。
修复后的完整代码
import functools import time def trace(times): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): total_time = 0 # 执行times次原函数调用,累计总耗时 for _ in range(times): start = time.time() result = func(*args, **kwargs) end = time.time() total_time += (end - start) # 打印平均运行时间 print(f"Average running time: {total_time / times:.8f} seconds") # 返回最后一次的计算结果 return result return wrapper return decorator # 修正转义问题,并调整递归逻辑避免触发装饰器 @trace(times=10) def fib(num): # 用内部函数处理递归,递归调用不会触发外层的计时逻辑 def inner(n): if n < 2: return n return inner(n - 1) + inner(n - 2) return inner(num) # 调用测试 print(f"fib(5) result: {fib(5)}")
关键修复细节解释
- 修正HTML转义:把
num < 2改为num < 2,解决语法错误。 - 调整返回值:
wrapper函数最后返回的是result(即func(*args, **kwargs)的计算结果),而不是函数对象func,这样调用fib(5)能得到正确的斐波那契数。 - 避免递归触发计时:我们在
fib内部定义了inner函数处理递归逻辑,这样外层的fib被装饰后,递归调用的是未被装饰的inner函数,只有最外层的fib(5)调用会执行10次重复计时,完全符合你的需求。
额外优化建议
因为斐波那契递归会有大量重复计算,导致fib(5)的运行时间极短(可能接近0),计时结果不够准确。你可以给inner函数加上functools.lru_cache缓存,减少重复计算,同时让计时结果更稳定:
import functools # ... 其他代码不变 ... @trace(times=10) def fib(num): @functools.lru_cache(maxsize=None) def inner(n): if n < 2: return n return inner(n - 1) + inner(n - 2) result = inner(num) inner.cache_clear() # 清空缓存,避免影响下一次计时 return result
内容的提问来源于stack exchange,提问作者user17751265
相关产品推荐
相关产品推荐

