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 字符串定义
Sep 25 Python
Django admin实现图书管理系统菜鸟级教程完整实例
Dec 12 Python
Python操作mysql数据库实现增删查改功能的方法
Jan 15 Python
解决Pandas to_json()中文乱码,转化为json数组的问题
May 10 Python
对python中for、if、while的区别与比较方法
Jun 25 Python
python实现录音小程序
Oct 26 Python
Python中如何使用if语句处理列表实例代码
Feb 24 Python
Python后台开发Django的教程详解(启动)
Apr 08 Python
在Python 的线程中运行协程的方法
Feb 24 Python
python如何将两张图片生成为全景图片
Mar 05 Python
python实现按日期归档文件
Jan 30 Python
python turtle绘图
May 04 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
很温暖很温暖的Lester Young
2021/03/03 冲泡冲煮
组合算法的PHP解答方法
2012/02/04 PHP
PHP判断图片格式的七种方法小结
2013/06/03 PHP
php有道翻译api调用方法实例
2014/12/22 PHP
变量在 PHP7 内部的实现(一)
2015/12/21 PHP
浅谈socket同步和异步、阻塞和非阻塞、I/O模型
2016/12/15 PHP
实现php删除链表中重复的结点
2018/09/27 PHP
PHP fopen函数用法实例讲解
2019/02/15 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
PHP设计模式(七)组合模式Composite实例详解【结构型】
2020/05/02 PHP
[原创]图片分页查看
2006/08/28 Javascript
jquery创建一个ajax关键词数据搜索实现思路
2013/02/26 Javascript
js调用iframe实现打印页面内容的方法
2014/03/04 Javascript
JavaScript中Date.toSource()方法的使用教程
2015/06/12 Javascript
如何利用JS通过身份证号获取当事人的生日、年龄、性别
2016/01/22 Javascript
jQuery Mobile 和 Kendo UI 的比较
2016/05/05 Javascript
如何用JS判断两个数字的大小
2016/07/21 Javascript
jQuery密码强度验证控件使用详解
2017/01/05 Javascript
微信小程序“摇一摇”的实例代码
2017/07/20 Javascript
JavaScript中Require调用js的实例分享
2017/10/27 Javascript
微信小程序如何获取用户头像和昵称
2019/09/23 Javascript
vue把输入框的内容添加到页面的实例讲解
2019/11/11 Javascript
js实现多个标题吸顶效果
2020/01/08 Javascript
Jquery高级应用Deferred对象原理及使用实例
2020/05/28 jQuery
Python中的CURL PycURL使用例子
2014/06/01 Python
python中pandas.DataFrame排除特定行方法示例
2017/03/12 Python
python MysqlDb模块安装及其使用详解
2018/02/23 Python
如何用Python来搭建一个简单的推荐系统
2019/08/07 Python
python 计算方位角实例(根据两点的坐标计算)
2020/01/17 Python
javascript实现用户必须勾选协议实例讲解
2021/03/24 Javascript
电脑专业个人求职信范文
2014/02/04 职场文书
课外活动实习计划
2015/01/19 职场文书
2015学校师德师风工作总结
2015/04/22 职场文书
85句关于理想的名言警句大全
2019/08/22 职场文书
python playwright 自动等待和断言详解
2021/11/27 Python
Java多线程并发FutureTask使用详解
2022/06/28 Java/Android