【计时方法】三、timeit

我们可以用 timeit 模块作为另一种测量执行时间的方法。通常来说,在解决问题的过程中会用它来为各种简单的语句计时。

注意,timeit 模块暂时禁用了垃圾收集器。如果你的操作会调用到垃圾收集器,那么它有可能影响到实际操作的速度。更多信息请参考 Python 文档:http://bit.ly/timeit_doc

命令行运行

假设需要运行 test.py 文件中的 somefunc 函数,并且命令行已经进入 test.py 所在的文件目录,可以从命令行运行 timeit 如下:

python -m timeit -n 5 -r 5 -s "import test" "test.somefunc()"

注意,必须以 -s 命令在设置阶段导入 test 模块,因为 somefunc 函数来自那个模块。timeit 有一些合理的默认值适用于一段简短的代码,但对于要长期运行的代码来说,最好指定循环次数(-n 5)以及重复次数(-r 5)。timeit 会对语句循环执行 n 次并计算平均值作为一个结果,重复 r 次并选出最好的那个结果。

如果我们不指定 -n 和 -r 运行 timeit,默认是循环 10 次重复 5 次,改变默认值可以更快获得我们需要的结果。

IPython 魔法函数

另外,在 IPython 内部,我们可以用同样的方式使用 %timeit 魔法函数。如果你在 IPython 中用互动的方式开发代码且函数在本地命名空间,那么可以用:

%timeit somefunc()

python 文件中运行

import timeit

# 待测试的函数
def add():
    return sum(range(111))
 
# stmt 需要测试的函数或语句,字符串形式
# setup 运行的环境,本例子中表示 if __name__ == '__main__':
# number 被测试的函数或语句,执行的次数,本例表示执行100000次add()。省缺则默认是10000次
# 综上:此函数表示在if __name__ == '__main__'的条件下,执行100000次add()消耗的时间
t = timeit.timeit(stmt="add()", setup="from  __main__ import add", number=100000)
print(t)

那么如果当下有这样的需求:测试 add 函数执行 100k 的时间,且把测试 100 遍,然后求平均值。timeit 无论每次测试执行多少变,但这个测试只进行一遍。有的小伙伴说可以使用 for 循环 100 次不就可以了,其实 timeit 中还有更有效的办法:repeat 函数

import timeit

# 待测试的函数
def add():
    return sum(range(111))

# stmt 需要测试的函数或语句,字符串形式
# setup 运行的环境,本例子中表示 if __name__ == '__main__':
# number 被测试的函数或语句,执行的次数,本例表示执行100000次add()。省缺则默认是10000次
# repeat 测试做100次
# 综上:此函数表示 测试 在if __name__ == '__main__'的条件下,执行100000次add()消耗的时间,并把这个测试做100次,并求出平均值
 
t = timeit.repeat(stmt="add()", setup="from __main__ import add", number=100000, repeat=100)
print(t)