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

如何使用Decorator装饰器打印递归函数调用并生成递归树

递归调用树打印装饰器实现

原代码缺陷说明

你之前写的装饰器存在三个核心问题,无法实现预期效果:

  • 包装函数未透传原递归函数的返回值,递归链路执行到第一层后就会中断,无法触发完整的深层递归
  • 没有递归深度追踪逻辑,无法将同一递归层级的调用归集到同一行输出
  • 未区分顶层入口调用和递归内层调用,无法在全量递归执行完成后统一输出结构化的调用树

可直接使用的实现代码

完全不需要修改原有fib函数的内部逻辑,直接替换装饰器即可:

def print_call_tree(function):
    def wrapper(n):
        # 最外层入口调用时初始化递归状态
        if not hasattr(wrapper, 'is_running'):
            wrapper.is_running = True
            wrapper.current_depth = 0
            wrapper.level_records = []
            try:
                result = wrapper(n)
                # 全量递归执行完成后按层级打印
                print(f"for n = {n}:")
                for calls in wrapper.level_records:
                    print("    " + ", ".join(calls))
                return result
            finally:
                # 清理状态,避免多次调用装饰器函数时数据互相污染
                del wrapper.is_running
                del wrapper.current_depth
                del wrapper.level_records
        # 所有递归调用的通用记录逻辑
        call_repr = f"{function.__name__}({n})"
        # 初始化当前深度的记录列表
        if len(wrapper.level_records) <= wrapper.current_depth:
            wrapper.level_records.append([])
        wrapper.level_records[wrapper.current_depth].append(call_repr)
        # 进入下一层递归,深度+1
        wrapper.current_depth += 1
        res = function(n)
        # 退出当前层回到上一层,深度-1
        wrapper.current_depth -= 1
        return res
    return wrapper


# 原有fib函数无需任何修改
@print_call_tree
def fib(n):
    if n < 3: return 1
    return fib(n-1) + fib(n-2)


# 测试调用
fib(5)

输出效果

执行fib(5)时的输出和预期结构完全一致:

for n = 5:
    fib(5)
    fib(4), fib(3)
    fib(3), fib(2), fib(2), fib(1)
    fib(2), fib(1), fib(1), fib(0)

注:你示例中出现的fib(-1)是因为示例用的fib终止条件和你给出的代码不一致,如果你把fib的终止条件改为if n < 2: return 1,就会自动打印出更深层的调用节点,装饰器不需要做任何调整。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 03:12:19