Python timeit模块详解:timeit()、repeat()与Timer类实战
本文深入解析Python标准库timeit模块,详细介绍timeit()、repeat()函数及Timer类的参数与用法。通过对比列表头部插入与尾部追加的性能差异,演示如何准确测量函数与代码块的执行时间,帮助开发者进行Python代码性能分析与优化。
Python timeit模块概述与导入方式
Python内置的timeit模块专门用于精确测量代码片段的执行耗时,无论是简单的变量赋值还是复杂的函数调用,均可通过该模块获取准确的运行时间数据。
作为Python标准库的一部分,timeit模块无需额外安装即可直接使用。通过直接导入import timeit,开发者可以调用timeit()函数、repeat()函数以及Timer类。需要注意的是,若使用from timeit import ...语法导入,受限于__all__全局变量定义,仅能导入Timer类。
timeit模块的源代码精简,总计仅300余行,核心逻辑即围绕前述两个函数和一个类展开,开发者感兴趣时可查阅源码以深入理解其实现机制。
接下来将实际演示如何使用timeit模块进行性能测试,本例旨在对比Python列表在头部插入数据与尾部追加数据两种操作下的执行效率差异,具体测试目标可根据实际需求调整。
使用timeit()函数测试代码耗时
一、利用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执行所需的前置环境,包括导入的模块、初始化的参数或变量等。例如setup = 'from __main__ import func'(__main__代表当前脚本文件)。支持单行或多行语句,多行语句间需使用分号分隔。
stmt与setup的默认值均为pass。若不提供具体测试代码,测试将失去意义,因此这两个参数是执行测试的必要条件。
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()函数进行多次重复测试
二、利用repeat()函数进行时间测试
1. repeat(stmt="pass", setup="pass", timer=default_timer, repeat=default_repeat, number=default_number) 函数解析
repeat()函数包含五个关键字参数,均设有默认值。相较于timeit()函数,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类进行灵活性能测试
三、利用Timer类进行时间测试
1. Timer类解析
前文使用的timeit()和repeat()函数,实质上是对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模块相对简单,上述即为主要用法。
本文内容至此结束,希望能为读者的学习提供帮助,欢迎继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









