Python使用timer_func装饰器统计递归斐波那契耗时重复打印日志问题
问题原因
- 首先是装饰器被重复嵌套:你已经用
@timer_func语法糖给fibonacci函数加了一层装饰,此时fibonacci本身已经是带计时逻辑的包装函数,后续调用timer_func(fibonacci)(5)等于又给它套了第二层计时装饰,两层逻辑同时生效。 - 核心原因是递归调用触发了多次装饰逻辑:被装饰后的
fibonacci函数每次递归调用fibonacci(x-1)、fibonacci(x-2)时,本质都是在调用带计时逻辑的包装函数,每执行一次递归就会打印一次耗时日志,自然会出现多条打印结果,而非仅统计最外层的总耗时。
解决方案
这里提供两种常用的修复方式:
方案1:仅对最外层调用加计时,不装饰递归函数
移除fibonacci函数上的@timer_func装饰器,只在需要统计耗时的最外层调用时套装饰器即可,此时递归内部调用的是原生未被装饰的fibonacci,不会触发多次打印:
from time import perf_counter import logging def timer_func(func): def inner_func(*args): t1 = perf_counter() res = func(*args) t2 = perf_counter() logging.log(logging.INFO, f"Done in {t2 - t1} Seconds!") return res return inner_func # 移除此处的@timer_func装饰 def fibonacci(x: int): if x > 2: return fibonacci(x - 1) + fibonacci(x - 2) elif x == 1 or x == 2: return 1 # 仅最外层调用加计时 r = timer_func(fibonacci)(5) print("Fibonacci %d of is %d" % (5, r))
方案2:给装饰器增加最外层调用判断,保留对函数的装饰
如果希望fibonacci本身自带计时能力、仅统计首次调用的总耗时,可以给装饰器加个调用层级标记,只有最外层调用执行完成后才打印日志:
from time import perf_counter import logging def timer_func(func): call_depth = 0 def inner_func(*args): nonlocal call_depth t1 = perf_counter() if call_depth == 0 else None call_depth += 1 res = func(*args) call_depth -= 1 if call_depth == 0: t2 = perf_counter() logging.log(logging.INFO, f"Done in {t2 - t1} Seconds!") return res return inner_func @timer_func def fibonacci(x: int): if x > 2: return fibonacci(x - 1) + fibonacci(x - 2) elif x == 1 or x == 2: return 1 # 直接调用即可,无需再额外套一层timer_func r = fibonacci(5) print("Fibonacci %d of is %d" % (5, r))
额外注意:已经用@timer_func装饰过的函数,直接调用即可,不需要再额外套timer_func(fibonacci),否则会重复添加装饰逻辑。
内容的提问来源于stack exchange,提问作者Levi
相关产品推荐
相关产品推荐

