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

Python:统计排序算法交换次数的装饰器遇到的问题

问题:排序算法交换次数统计的装饰器问题

我想写个装饰器统计排序算法的交换次数,于是写了交换函数swap和统计调用次数的装饰器swapCounter,现在碰到两个问题:

  • 统计多个排序算法时,交换次数会累加,不会重置
  • 每次交换都会在控制台打印信息

我试着给装饰器和swap函数加标记重置计数,结果出现AttributeError: 'function' object has no attribute 'calls'报错。相关代码如下:

初始版本代码

装饰器

def swapCounter(func):
    def counter(*args, **kwargs):
        counter.calls += 1
        print(f"Swaps {counter.calls}")
        return func(*args, **kwargs)
    counter.calls = 0
    return counter

交换函数

def swap(arr, i, j):
        arr[i], arr[j] = arr[j], arr[i]

示例排序算法

def bubbleSort(arr):
    for i in range(len(arr)):
        for j in range(0, len(arr)-i-1):
            if arr[j] > arr[j+1]:
                swap(arr, j, j+1)

    return arr

尝试修改的代码

修改后的装饰器

def swapCounter(func):
    def counter(*args, **kwargs):
        counter.calls+=1
        if kwargs.get("flag")==True:
            print(f"Swaps {counter.calls}")
            counter.calls = 0
            return func(*args, **kwargs)
    return counter

修改后的交换函数

def swap(arr=None, i=None, j=None, flag=None):
        arr[i], arr[j] = arr[j], arr[i]

修改后的排序算法

def bubbleSort(arr):
    for i in range(len(arr)):
        for j in range(0, len(arr)-i-1):
            if arr[j] > arr[j+1]:
                swap(arr, j, j+1)

    swap(True)

解决方案

问题根源

你修改后的装饰器没有初始化counter.calls = 0,第一次调用时变量不存在才触发AttributeError;另外全局共享计数变量会导致多算法调用时累加,同时实时打印逻辑也不符合只看最终结果的需求。

优化后的装饰器实现

我们让装饰器支持手动重置计数、获取最终次数,同时关闭实时打印:

def swapCounter(func):
    def counter(*args, **kwargs):
        # 处理计数重置请求
        if kwargs.get("reset"):
            counter.calls = 0
            return
        # 处理获取计数请求
        if kwargs.get("get_count"):
            return counter.calls
        # 正常执行交换并计数
        counter.calls += 1
        return func(*args, **kwargs)
    # 初始化计数变量,解决属性不存在报错
    counter.calls = 0
    return counter

# 给swap函数绑定装饰器
@swapCounter
def swap(arr, i, j):
    arr[i], arr[j] = arr[j], arr[i]

排序算法的正确使用方式

每个排序算法执行前重置计数,结束后获取并打印最终次数:

def bubbleSort(arr):
    # 排序前重置计数
    swap(reset=True)
    for i in range(len(arr)):
        for j in range(0, len(arr)-i-1):
            if arr[j] > arr[j+1]:
                swap(arr, j, j+1)
    # 排序结束后获取并打印交换次数
    swap_count = swap(get_count=True)
    print(f"冒泡排序交换次数:{swap_count}")
    return arr

def selectionSort(arr):
    swap(reset=True)
    for i in range(len(arr)):
        min_idx = i
        for j in range(i+1, len(arr)):
            if arr[j] < arr[min_idx]:
                min_idx = j
        if min_idx != i:
            swap(arr, i, min_idx)
    swap_count = swap(get_count=True)
    print(f"选择排序交换次数:{swap_count}")
    return arr

核心改进点

  1. 装饰器初始化计数变量,彻底解决AttributeError问题
  2. 新增reset参数,每个排序任务前单独重置计数,避免跨算法累加
  3. 新增get_count参数,只在排序结束后打印一次结果,取消实时打印
  4. 保留原swap函数的简洁参数结构,无需冗余标记参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:45:03