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 相关文章推荐
详解python中requirements.txt的一切
Mar 03 Python
开源Web应用框架Django图文教程
Mar 09 Python
pygame实现弹力球及其变速效果
Jul 03 Python
Python网络爬虫神器PyQuery的基本使用教程
Feb 03 Python
Pandas:DataFrame对象的基础操作方法
Jun 07 Python
Python根据文件名批量转移图片的方法
Oct 21 Python
windows中安装Python3.8.0的实现方法
Nov 19 Python
解决Django中checkbox复选框的传值问题
Mar 31 Python
浅谈keras使用预训练模型vgg16分类,损失和准确度不变
Jul 02 Python
Python OpenCV读取中文路径图像的方法
Jul 02 Python
Django使用django-simple-captcha做验证码的实现示例
Jan 07 Python
Python Pytorch查询图像的特征从集合或数据库中查找图像
Apr 09 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
php将数据库中所有内容生成静态html文档的代码
2010/04/12 PHP
php后台如何避免用户直接进入方法实例
2013/10/15 PHP
PHP输出当前进程所有变量/常量/模块/函数/类的示例
2013/11/07 PHP
php无序树实现方法
2015/07/28 PHP
jquery 模式对话框终极版实现代码
2009/09/28 Javascript
js中top/parent/frame概述及案例应用
2013/02/06 Javascript
用jQuery实现一些导航条切换,显示隐藏的实例代码
2013/06/08 Javascript
js创建对象的区别示例介绍
2014/07/24 Javascript
深入浅析JavaScript中对事件的三种监听方式
2015/09/29 Javascript
详解Javascript继承的实现
2016/03/25 Javascript
动态设置form表单的action属性的值的简单方法
2016/05/25 Javascript
jQuery post数据至ashx实例详解
2016/11/18 Javascript
BootStrapTable 单选及取值的实现方法
2017/01/10 Javascript
vue2.0 自定义日期时间过滤器
2017/06/07 Javascript
快速掌握jquery分页插件jqPaginator的使用方法
2017/08/09 jQuery
深入理解ES6的迭代器与生成器
2017/08/19 Javascript
JSON创建键值对(key是中文或者数字)方式详解
2017/08/24 Javascript
利用Console来Debug的10个高级技巧汇总
2018/03/26 Javascript
微信小程序 拍照或从相册选取图片上传代码实例
2019/08/28 Javascript
vue实现点击出现操作弹出框的示例
2020/11/05 Javascript
[02:56]DOTA2矮人直升机 英雄基础教程
2013/11/26 DOTA
Python简单计算文件MD5值的方法示例
2018/04/11 Python
numpy.ndarray 交换多维数组(矩阵)的行/列方法
2018/08/02 Python
使用Python批量修改文件名的代码实例
2019/01/24 Python
Python实现寻找回文数字过程解析
2020/06/09 Python
python3爬虫中多线程进行解锁操作实例
2020/11/25 Python
介绍下Java的输入输出流
2014/01/22 面试题
JDK安装目录下有哪些内容
2014/08/25 面试题
"序列点" 是什么
2016/07/29 面试题
超市实习总结自我鉴定
2013/09/19 职场文书
公务员个人自我评价分享
2013/11/06 职场文书
介绍信格式样本
2015/05/05 职场文书
《七律·长征》教学反思
2016/02/16 职场文书
HTML页面滚动时部分内容位置固定不滚动的实现
2021/04/14 HTML / CSS
Vue深入理解插槽slot的使用
2022/08/05 Vue.js
Python 第三方库 openpyxl 的安装过程
2022/12/24 Python