You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为带记忆化的递归函数实现单次计时的装饰器?

解决递归函数计时装饰器重复输出的问题

你的问题根源在于:装饰器直接替换了fib_mem函数,递归调用fib_mem时,实际调用的是被装饰后的inner函数,导致每一次递归都会执行计时逻辑,从而多次输出时间。而fib_rec没问题是因为它的递归是调用内部嵌套的fibo函数,而非被装饰的fib_rec本身。

下面是修改后的装饰器,仅对最外层函数调用执行一次计时:

from time import timer
from typing import Callable
from functools import wraps

def time_dec(func: Callable):
    @wraps(func)
    def inner(*args, **kwargs):
        # 用函数属性标记是否正在执行最外层计时
        if not getattr(inner, '_in_timing', False):
            inner._in_timing = True
            t1 = timer()
            try:
                # 执行原函数,保留返回值
                result = func(*args, **kwargs)
            finally:
                # 无论函数是否抛出异常,都打印耗时并重置状态
                print(f"函数执行耗时:{timer() - t1:.6f}秒")
                inner._in_timing = False
            return result
        else:
            # 递归调用时直接执行原函数,跳过计时逻辑
            return func(*args, **kwargs)
    return inner

为什么这个方案有效:

  • 通过给inner函数添加_in_timing属性,追踪当前是否处于最外层计时状态
  • 第一次调用时,设置_in_timing为True,执行完整的计时流程;递归调用时,因_in_timing已为True,直接调用原函数,不触发计时打印
  • 使用try...finally确保即使函数执行出错,也能重置计时状态,避免后续调用异常
  • @wraps(func)保留原函数的元信息(如函数名、文档字符串),避免装饰器破坏原函数的特性

测试修改后的装饰器

用修改后的装饰器装饰fib_mem:

cache = {0: 0, 1: 1}
@time_dec
def fib_mem(n):
    if n in cache:
        return cache[n]
    cache[n] = fib_mem(n - 1) + fib_mem(n - 2)
    return cache[n]

调用fib_mem(20)只会输出一次完整的执行耗时,符合你的需求。

内容的提问来源于stack exchange,提问作者Roggab32

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:00:03