Python装饰器计时结果与直接调用计时结果不一致原因咨询
装饰器计时与直接计时结果不一致的原因
代码
from time import time def speed_test(func): def wrapper(*args, **kwargs): start = time() func(*args, **kwargs) end = time() - start print(f"Execution time is: {end:.17f}s # Decorator") return wrapper @speed_test def sorting(L): L.sort() # For example def sorting_1(L1): L1.sort() T = [10, 5, 3, 1, 0] L = T.copy() sorting(T) a = time() sorting_1(L) b = time() - a print(f"Execution time is: {b:.17f}s # Main")
预期输出
Execution time is: 0.00000977516174316s # Decorator Execution time is: 0.00000977516174316s # Main
实际输出
Execution time is: 0.00000977516174316s # Decorator Execution time is: 0.00000572204589844s # Main
差异原因
核心问题是两次排序的列表状态完全不同:
- 调用
sorting(T)时,T是未排序的原始列表[10,5,3,1,0],L.sort()需要完成完整的排序操作,耗时较长。 - 执行完
sorting(T)后,T已经被排序为[0,1,3,5,10],而L = T.copy()复制的是这个已完全有序的列表。后续调用sorting_1(L)时,L.sort()处理的是有序序列,Python内置的Timsort算法对完全有序的序列有极致优化,几乎不需要执行交换操作,因此耗时远低于第一次排序。
装饰器的wrapper函数会带来极其微小的调用开销,但这不是本次差异的主要原因,核心还是列表是否有序的问题。
如果要验证这个结论,可以做两个调整:
- 调换两个函数的调用顺序,先调用
sorting_1(L)再调用sorting(T),会看到第一次计时更长,第二次更短; - 给L重新赋值为未排序的列表,比如
L = [10,5,3,1,0].copy(),此时两次计时结果会基本一致。
内容的提问来源于stack exchange,提问作者Ghoudiy
相关产品推荐
相关产品推荐

