Python timeit模块原理及使用方法


Posted in Python onOctober 10, 2020

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 模块是一个比较简单的模块,大概用法就这些了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
windows系统中python使用rar命令压缩多个文件夹示例
May 06 Python
Python中的time模块与datetime模块用法总结
Jun 30 Python
使用memory_profiler监测python代码运行时内存消耗方法
Dec 03 Python
Linux下远程连接Jupyter+pyspark部署教程
Jun 21 Python
pandas数据处理进阶详解
Oct 11 Python
Python3 Click模块的使用方法详解
Feb 12 Python
利用Python脚本批量生成SQL语句
Mar 04 Python
python上传时包含boundary时的解决方法
Apr 08 Python
Python如何爬取51cto数据并存入MySQL
Aug 25 Python
scrapy redis配置文件setting参数详解
Nov 18 Python
如何使用Tkinter进行窗口的管理与设置
Jun 30 Python
详细介绍python操作RabbitMq
Apr 12 Python
python实现自动打卡的示例代码
Oct 10 #Python
Python类绑定方法及非绑定方法实例解析
Oct 09 #Python
Python批量获取并保存手机号归属地和运营商的示例
Oct 09 #Python
Python判断变量是否是None写法代码实例
Oct 09 #Python
Python尾递归优化实现代码及原理详解
Oct 09 #Python
Python hashlib模块的使用示例
Oct 09 #Python
浅析Python requests 模块
Oct 09 #Python
You might like
基于mysql的论坛(5)
2006/10/09 PHP
ioncube_loader_win_5.2.dll的错误解决方法
2015/01/04 PHP
jquery+ajax验证不通过也提交表单问题处理
2014/12/12 Javascript
微信JS接口汇总及使用详解
2015/01/09 Javascript
JavaScript获得当前网页来源页面(即上一页)的方法
2015/04/03 Javascript
Javascript动态创建表格及删除行列的方法
2015/05/15 Javascript
基于Bootstrap+jQuery.validate实现表单验证
2016/05/30 Javascript
nodejs简单实现TCP服务器端和客户端的聊天功能示例
2018/01/04 NodeJs
解决bootstrap中下拉菜单点击后不关闭的问题
2018/08/10 Javascript
前后端如何实现登录token拦截校验详解
2018/09/03 Javascript
浅谈layui使用模板引擎动态渲染元素要注意的问题
2019/09/14 Javascript
支付宝小程序实现省市区三级联动
2020/06/21 Javascript
在vue中获取wangeditor的html和text的操作
2020/10/23 Javascript
[05:41]2014DOTA2西雅图国际邀请赛 小组赛7月10日TOPPLAY
2014/07/10 DOTA
用python实现的可以拷贝或剪切一个文件列表中的所有文件
2009/04/30 Python
举例讲解Django中数据模型访问外键值的方法
2015/07/21 Python
Python编程实现数学运算求一元二次方程的实根算法示例
2017/04/02 Python
Python编程之基于概率论的分类方法:朴素贝叶斯
2017/11/11 Python
Python使用progressbar模块实现的显示进度条功能
2018/05/31 Python
浅析python3字符串格式化format()函数的简单用法
2018/12/07 Python
使用python实现简单五子棋游戏
2019/06/18 Python
Python传递参数的多种方式(小结)
2019/09/18 Python
python通过opencv实现图片裁剪原理解析
2020/01/19 Python
python连接mysql数据库并读取数据的实现
2020/09/25 Python
Python爬虫如何破解JS加密的Cookie
2020/11/19 Python
python脚本使用阿里云slb对恶意攻击进行封堵的实现
2021/02/04 Python
英国航空官网:British Airways
2016/09/11 全球购物
流行文化收藏品:Sideshow(DC漫画,星球大战,漫威)
2019/03/17 全球购物
请用Python写一个获取用户输入数字,并根据数字大小输出不同信息的脚本
2014/05/20 面试题
2014年上半年工作自我评价
2014/01/18 职场文书
煤矿班组长竞聘书
2014/03/31 职场文书
党课培训主持词
2014/04/01 职场文书
人事经理岗位职责范本
2014/08/04 职场文书
全国法制宣传日活动总结2014
2014/11/01 职场文书
工作感言一句话
2015/08/01 职场文书
vue-cropper插件实现图片截取上传组件封装
2021/05/27 Vue.js