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
核心改进点
- 装饰器初始化计数变量,彻底解决
AttributeError问题 - 新增
reset参数,每个排序任务前单独重置计数,避免跨算法累加 - 新增
get_count参数,只在排序结束后打印一次结果,取消实时打印 - 保留原
swap函数的简洁参数结构,无需冗余标记参数
内容的提问来源于stack exchange,提问作者UsernameTHC
相关产品推荐
相关产品推荐

