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

如何在递归函数中使用Python装饰器?解决计时重复输出问题

解决递归函数计时装饰器重复输出问题,兼容迭代函数

原装饰器的问题在于递归调用时每一层都会触发计时逻辑,导致输出多个耗时值。我们需要修改装饰器,让它只在最外层调用时统计总耗时,同时保持对迭代函数的兼容性。

方案1:单线程场景简易实现

利用函数属性标记当前是否处于计时流程中,仅在最外层执行计时逻辑:

import datetime

def timed(func):
    def wrapper(*args, **kwargs):
        # 判断是否为最外层调用
        if not wrapper._is_timing:
            wrapper._is_timing = True
            start = datetime.now()
            result = func(*args, **kwargs)
            elapsed = datetime.now() - start
            print(f"总耗时: {elapsed.microseconds / 1000} ms")
            wrapper._is_timing = False
            return result
        # 内层递归调用,直接执行原函数
        return func(*args, **kwargs)
    
    # 初始化计时标志
    wrapper._is_timing = False
    return wrapper

原理说明

  • 给wrapper函数添加_is_timing属性,作为是否正在计时的标记
  • 首次调用(最外层)时,_is_timing为False,开启计时并执行原函数,结束后输出总耗时并重置标记
  • 递归调用时,_is_timing已被设为True,直接执行原函数,不触发计时输出

方案2:多线程安全实现

如果你的代码涉及多线程调用,使用线程局部存储避免不同线程的计时状态互相干扰:

import datetime
import threading

def timed(func):
    # 线程局部变量,每个线程独立维护计时状态
    local_state = threading.local()
    
    def wrapper(*args, **kwargs):
        # 检查当前线程是否处于计时中
        if not getattr(local_state, 'is_timing', False):
            local_state.is_timing = True
            start = datetime.now()
            result = func(*args, **kwargs)
            elapsed = datetime.now() - start
            print(f"总耗时: {elapsed.microseconds / 1000} ms")
            local_state.is_timing = False
            return result
        return func(*args, **kwargs)
    return wrapper

测试验证

归并排序(递归函数)

使用修改后的装饰器装饰merge函数:

def _merge_sorted(l, r):
    i = j = 0
    temp = []
    while i < len(l) and j < len(r):
        if l[i] <= r[j]:
            temp.append(l[i])
            i += 1
        else:
            temp.append(r[j])
            j += 1
    temp.extend(l[i:])
    temp.extend(r[j:])
    return temp

@timed
def merge(arr):
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left = merge(arr[:mid])
    right = merge(arr[mid:])
    return _merge_sorted(left, right)

# 调用后仅输出一次总耗时
merge([5,4,3,2,1])

输出示例:

总耗时: 0.062 ms

冒泡排序(迭代函数)

装饰迭代函数也能正常工作:

@timed
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        swapped = False
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
                swapped = True
        if not swapped:
            break
    return arr

bubble_sort([5,4,3,2,1])

输出示例:

总耗时: 0.038 ms

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 16:54:22