Python timeit模块原理及使用方法
作者:lincappu 发布时间:2023-09-22 08:19:18
Python 中的 timeit 模块可以用来测试一段代码的执行耗时,如一个变量赋值语句的执行时间,一个函数的运行时间等。
timeit 模块是 Python 标准库中的模块,无需安装,直接导入就可以使用。导入时直接 import timeit ,可以使用 timeit() 函数和 repeat() 函数,还有 Timer 类。使用 from timeit import ... 时,只能导入 Timer 类(有全局变量 __all__ 限制)。
timeit 模块的源码总共只有 300 多行,主要就是实现上面的两个函数和一个类,可以自己看一下。
接下来就开始使用 timeit 模块来测试代码执行时间,我使用 timeit 模块来对比 Python 列表从头部添加数据和从尾部添加数据的执行时间(测试什么根据需求来定)。
一、使用 timeit() 函数测试运行时间
1. 准备测试函数
先写两个函数,一个函数是从列表头部添加数据,另一个函数是从列表尾部添加数据。
#
coding = utf - 8
def insert_time_test():
insert_list = list()
for i in range(10):
insert_list.insert(0, i)
def append_time_test():
append_list = list()
for i in range(10):
append_list.append(i)
if __name__ == '__main__':
import timeit
# coding = utf - 8
def insert_time_test():
insert_list = list()
for i in range(10):
insert_list.insert(0, i)
def append_time_test():
append_list = list()
for i in range(10):
append_list.append(i)
if __name__ == '__main__':
import timeit
2. timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number) 函数介绍
timeit() 函数有四个参数,每个参数都是关键字参数,都有默认值。
stmt:传入需要测试时间的代码,可以直接传入代码表达式或单个变量,也可以传入函数。传入函数时要在函数名后面加上小括号,让函数执行,如 stmt = ‘func()' 。
setup:传入 stmt 的运行环境,如 stmt 中使用到的参数、变量,要导入的模块等,如 setup = ‘from __main__ import func' (__main__表示当前的文件)。可以写一行语句,也可以写多行语句,写多行语句时用分号隔开。
stmt 参数和 setup 参数默认值都是 pass,如果不传值,那么就失去了测试的意义,所以这两个参数是必要的。
timer: timer 参数是当前操作系统的基本时间单位,默认会根据当前运行环境的操作系统自动获取(源码中已经定义),保持默认即可。
number:要测试的代码的运行次数,默认1000000(一百万)次,对于耗时的代码,运行太多次会花很多时间,可以自己修改运行次数。
3. 测试函数的运行时间
现在使用 timeit() 来测试上面两个函数的运行时间。
insert_time_timeit = timeit.timeit(stmt='insert_time_test()',
setup='from __main__ import insert_time_test')
print('insert_time_timeit: ', insert_time_timeit)
append_time_timeit = timeit.timeit(stmt='append_time_test()',
setup='from __main__ import append_time_test')
print('append_time_timeit: ', append_time_timeit)
运行结果:
('insert_time_timeit: ', 2.9112871)
('append_time_timeit: ', 1.8884124999999998)
可以看到,在列表头部添加数据的时间比在列表尾部添加数据的时间长。
4. 测试代码(表达式)的运行时间
继续使用 timeit() 测试上面代码的运行时间,只是这次是直接将代码传入到参数中,而不是传入函数。
insert_time_timeit = timeit.timeit(stmt='list(insert_list.insert(0, i) for i in init_list)',
setup='insert_list=list();init_list=range(10)',
number=100000)
print('insert_time_timeit: ', insert_time_timeit)
append_time_timeit = timeit.timeit(stmt='list(append_list.append(i) for i in init_list)',
setup='append_list=list();init_list=range(10)',
number=100000)
print('append_time_timeit: ', append_time_timeit)
由于时间很长,代码 * 意将 number 从一百万次改成了十万次。运行结果如下:
('insert_time_timeit: ', 330.46189400000003)
('append_time_timeit: ', 0.21436310000001413)
相对来说,对于相同的操作,使用函数的运行时间远小于直接传入代码表达式的时间,头部插入数据的尤其明显。
二、使用 repeat() 函数测试运行时间
1. repeat(stmt="pass", setup="pass", timer=default_timer, repeat=default_repeat, number=default_number) 函数介绍
repeat() 函数有五个参数,每个参数都是关键字参数,都有默认值。相比 timeit() 函数而言,timeit() 函数有的参数 repeat() 函数都有,此外,repeat() 函数多了一个 repeat 参数。
repeat:表示测试要重复几次,可以理解为将相同参数的 timeit() 函数重复执行。最终的结果构成一个列表返回,repeat 默认为3次。
2. 测试函数的运行时间
现在使用 repeat() 来测试上面两个函数的运行时间。
insert_time_repeat = timeit.repeat(stmt='insert_time_test()',
setup='from __main__ import insert_time_test')
print('insert_time_repeat: ', insert_time_repeat)
append_time_repeat = timeit.repeat(stmt='append_time_test()',
setup='from __main__ import append_time_test')
print('append_time_repeat: ', append_time_repeat)
运行结果如下:
('insert_time_repeat: ', [2.7707739, 2.908885, 2.7164823999999994])
('append_time_repeat: ', [1.7458063, 1.777368000000001, 1.8675014999999995])
3. 测试代码(表达式)的运行时间
继续使用 repeat() 测试上面代码的运行时间,直接传入代码,上面将 number 改成十万次后,时间还是很长(300多秒),所以继续减小 number ,改成一万次。
insert_time_repeat = timeit.repeat(stmt='list(insert_list.insert(0, i) for i in init_list)',
setup='insert_list=list();init_list=range(10)',
repeat=5,
number=10000)
print('insert_time_repeat: ', insert_time_repeat)
append_time_repeat = timeit.repeat(stmt='list(append_list.append(i) for i in init_list)',
setup='append_list=list();init_list=range(10)',
repeat=5,
number=10000)
print('append_time_repeat: ', append_time_repeat)
运行结果如下:
('insert_time_repeat: ', [2.591015, 2.5814996999999997, 2.5547322, 2.6153070000000005, 2.5496864000000006])
('append_time_repeat: ', [0.0181692999999985, 0.01746889999999901, 0.018901899999999472, 0.018737400000000903, 0.018211900000000725])
三、使用 Timer 类测试运行时间
1. Timer 类介绍
上面使用了 timeit() 函数和 repeat() 函数,其实在 timeit 模块中,这两个函数都是对 Timer 类做了进一步的封装,实际调用的还是 Timer 类中的方法。
在 Timer 类中,实现了两个方法,timeit() 方法和 repeat() 方法,上面两个函数调用的就是这两个方法。
在使用 from timeit import ... 时,只能导入 Timer 类,所以可以直接使用 Timer 类来测试,可以自己去调用方法,使用起来更灵活。
2. 测试列表头部添加
先实例化一个 Timer 类的对象,实例化时传入 stmt 和 setup 参数(参数的含义与上面一致),timer 参数保持默认,然后通过实例对象调用对应的 timeit() 方法或 repeat() 方法,在 timeit() 方法中传入 number,在repeat() 方法中传入 number 和 repeat 。
使用 timeit() 方法和 repeat() 方法测试从头部添加数据的运行时间。
timer_insert = timeit.Timer(stmt='insert_time_test()', setup='from __main__ import insert_time_test')
insert_time_timeit = timer_insert.timeit(number=1000000)
print('insert_time_timeit: ', insert_time_timeit)
insert_time_repeat = timer_insert.repeat(number=1000000)
print('insert_time_repeat: ', insert_time_repeat)
运行结果如下:
('insert_time_timeit: ', 2.7732486)
('insert_time_repeat: ', [2.7367806999999997, 2.707402600000001, 2.7288245999999994])
3. 测试列表尾部添加
使用 timeit() 方法和 repeat() 方法测试从尾部添加数据的运行时间。
timer_append = timeit.Timer(stmt='append_time_test()', setup='from __main__ import append_time_test')
append_time_timeit = timer_append.timeit(number=1000000)
print('append_time_timeit: ', append_time_timeit)
append_time_repeat = timer_append.repeat(number=1000000)
print('append_time_repeat: ', append_time_repeat)
运行结果如下:
('append_time_timeit: ', 1.9966106000000001)
('append_time_repeat: ', [1.9523343999999998, 1.8373857999999998, 1.8695377000000004])
timeit 模块是一个比较简单的模块,大概用法就这些了。
来源:https://www.cnblogs.com/lincappu/p/13679652.html


猜你喜欢
- 问题:如何在报表中每隔N行显示一条粗线如何为报表增加一个行号列?回答:1、在设计模式里打开该报表,在报表主体里面加一个TextBox,把Na
- 本文实例讲述了python通过pil将图片转换成黑白效果的方法。分享给大家供大家参考。具体分析如下:pil功能强大,convert方法可以轻
- 本书的作者Douglas Crockford是JavaScript开发社区最知名的权威,JavaScript的发明人Brendan Eich
- 问题所在:当我们想让应用层和http之间的所有接口都采用json,这样,客户端代码就可以纯碎用javascript的对象来编写,服务器打啊也
- 这篇文章主要介绍了Python实现word2Vec model过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- MySQL支持的两种主要表存储格式MyISAM,InnoDB,上个月做个项目时,先使用了InnoDB,结果速度特别慢,1秒钟只能插入10几条
- 在pandas中,经常对数据进行处理 而导致数据索引顺序混乱,从而影响数据读取、插入等。小笔总结了以下几种重置索引的方法:import pa
- 当我们想更新一张动态表的时候(即:表中的数据不断的添加),也许我们会用数据库代理,通过写作业,然后让他定时查询动态表中最新添加的数据,然后更
- 本文实例讲述了Python网络编程使用select实现socket全双工异步通信功能。分享给大家供大家参考,具体如下:在前面一篇《Pytho
- 什么是词干提取?在语言形态学和信息检索里,词干提取是去除词缀得到词根的过程─—得到单词最一般的写法。对于一个词的形态词根,词干并不需要完全相
- 好了,下面就是满足你设想的几个主程序,你还可以在实际应用中不断完善和扩充:login.asp' 考生验证<%@&nb
- 在 Python 中,* 和 ** 具有语法多义性,具体来说是有四类用法。1. 算数运算* 代表乘法** 代表乘方>>>
- 本文实例讲述了MySQL数据库入门之多实例配置方法。分享给大家供大家参考,具体如下:前面介绍了相关的基础命令操作:MySQL数据库基础篇之入
- 这个问题已经不是什么新鲜问题了,网上也有大把的教程,但大多数是授人以鱼,而不授人以渔,经过辛苦的资料收集,思考,调试,整理,我基本上已经把这
- 这篇文章主要介绍了Python scrapy增量爬取实例及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 为什么使用虚拟环境因为直接在真实环境进行安装python的包会造成环境之间的污染,因此需要创建虚拟环境,原则上每一个项目都需要有一个独属于自
- 本文实例讲述了Python求一批字符串的最长公共前缀算法。分享给大家供大家参考,具体如下:思路一:这个题一拿到手,第一反应就是以第一个字符串
- 将json转为结构体时,经常会遇到无法确定某个字段类型的情况。在Go中可以使用interface 任意类型来解决。// convert js
- Vue加载流程1.初始化的第一阶段是Vue实例也就是vm对象创建前后:首先Vue进行生命周期,事件初始化发生在beforeCreate生命周
- 在默认情况下,Access 2000/2002数据库是以“共享”的方式打开的,这样可以保证多人能够同时使用同一个数据库。不过,在共享方式打开