在自定义函数中使用timeit.timer与从命令行调用时结果差异大

1 投票
1 回答
672 浏览
提问于 2025-04-17 14:52

我写了一个小函数,用来使用timeit,这样我可以懒一点,少打点字,但结果并没有按我想的那样进行。

相关的代码如下:

def timing(function, retries=10000, formatSeconds=3, repeat=10):
    """Test how long a function takes to run. Defaults are set to run
    10 times of 10000 tries each. Will display time as 1 of 4 types.
    0 = Seconds, 1 = milliseconds, 2= microseconds and 3 = nanoseconds.
    Pass in paramaters as: (function, retries=10000,formatSeconds=3, repeat=10)"""
    t = timeit.Timer(lambda: function)
    result = t.repeat(repeat=repeat,number=retries)
    rlist = [i/retries for i in result]

这个函数运行得很好,但它总是返回:

timeprofile.timing(find_boundaries(numpy.asarray(Image.open(
r'D:\Python\image\image4.jpg')),79))
    10 runs of 10000 cycles each: 
    Best time: 137.94764   Worst:158.16651  Avg: 143.25466 nanosecs/pass

现在,如果我在解释器中这样做:

import timeit
from timeit import Timer
t = timeit.Timer(lambda: (find_boundaries(numpy.asarray(Image.open(r'D:\Python\image\image4.jpg')),79)))
result = t.repeat(repeat=5,number=100)
result = [i/100 for i in result]

我得到的结果是 [0.007723014775432375, 0.007615270149786965, 0.0075242365377505395, 0.007420834966038683, 0.0074086862470653615],大约是8毫秒。

如果我在脚本上运行分析器,它也给出了大约8毫秒的结果。

我不太确定问题出在哪里,不过我觉得可能和调用这个函数的方式有关。当我在调试器中检查数据时,它显示这个函数是一个字典,长度为53,每个键里包含1到15个元组,每个元组里有一对2到3位的数字。

所以,如果有人知道为什么会这样,并愿意给我解释一下,顺便告诉我怎么解决,那就太好了!

1 个回答

3

是的,确实有区别。当你运行:

timeprofile.timing(find_boundaries(numpy.asarray(Image.open(
    r'D:\Python\image\image4.jpg')),79))

你并不是在传递一个函数的引用。你实际上是在调用这个函数,而是把调用的结果传了进去。你是在计时staticresult,而不是somefunction(with, arguments)

把lambda移出来:

timeprofile.timing(lambda: (find_boundaries(numpy.asarray(Image.open(
    r'D:\Python\image\image4.jpg')),79)))

这意味着你需要把它从你的timing函数中移除,而是直接把函数传给Timer()类:

t = timeit.Timer(function)

撰写回答