timeit
模块是 Python 标准库中用于测量小段代码执行时间的工具,特别适合比较不同实现方式的性能差异。
目录
1.基本用法
1.1 命令行使用
python -m timeit "代码语句"
# 例如
python -m timeit "'-'.join(str(n) for n in range(100))"
1.2 Python 程序中使用
import timeit
# 测量单条语句执行时间
t = timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
print(t)
# 测量多个语句
setup = '''
def func():
return "-".join(str(n) for n in range(100))
'''
t = timeit.timeit('func()', setup=setup, number=10000)
print(t)
2. 主要函数
-
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
-
stmt
: 要测量的代码语句 -
setup
: 执行前的初始化代码 -
number
: 执行次数 -
返回执行的总时间(秒)
-
-
timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000)
-
重复测量多次,返回时间列表
-
-
timeit.default_timer()
-
返回默认的计时器函数
-
3. 示例
3.1 比较两种字符串连接方式的性能
import timeit
# 使用 + 连接
concat_test = """
s = ""
for i in range(1000):
s += str(i)
"""
# 使用 join 连接
join_test = """
s = "".join(str(i) for i in range(1000))
"""
print("concat time:", timeit.timeit(concat_test, number=1000))
print("join time:", timeit.timeit(join_test, number=1000))
3.2 测量函数执行时间
import timeit
def test_func():
return sum(range(1000))
# 测量函数执行时间
t = timeit.timeit(test_func, number=10000)
print(f"执行10000次耗时: {t:.4f}秒")
4. 最佳实践
-
多次测量:使用
repeat()
多次测量取最小值,减少系统波动影响 -
合适的大小:选择适当的
number
参数,使总时间在 0.2-2 秒之间 -
避免副作用:确保被测代码没有副作用,或每次测试前重置状态
-
使用 setup:将初始化代码放在 setup 中,不计入测量时间
5. 高级用法
5.1 使用 Timer 类
from timeit import Timer
t = Timer('char in text', setup='text = "sample string"; char = "g"')
print(t.timeit()) # 默认执行100万次
print(t.repeat(repeat=3, number=1000000)) # 重复3次
5.2 在 Jupyter Notebook 中使用
%timeit sum(range(1000)) # 单行魔法命令
%%timeit # 多行魔法命令
total = 0
for i in range(1000):
total += i
timeit
模块是 Python 性能分析和优化的基础工具,特别适合微基准测试,帮助开发者找出更高效的代码实现方式。
下面提供几个实用的 timeit
模块应用实例,展示如何在实际开发中使用它来测量和比较代码性能。
实例1:比较列表创建方式的性能
import timeit
# 测试列表推导式 vs append方法
list_comp = timeit.timeit('[x**2 for x in range(1000)]', number=10000)
list_append = timeit.timeit('''
result = []
for x in range(1000):
result.append(x**2)
''', number=10000)
print(f"列表推导式: {list_comp:.5f}秒")
print(f"append方法: {list_append:.5f}秒")
print(f"性能差异: {(list_append/list_comp):.2f}倍")
实例2:字符串格式化方法比较
import timeit
# 测试不同字符串格式化方法的性能
methods = {
"%格式化": '"Name: %s, Age: %d" % ("Alice", 30)',
"str.format": '"Name: {}, Age: {}".format("Alice", 30)',
"f-string": 'name="Alice"; age=30; f"Name: {name}, Age: {age}"'
}
for name, code in methods.items():
# 使用setup消除变量创建时间的影响
t = timeit.timeit(code,
setup='name="Alice"; age=30',
number=100000)
print(f"{name}: {t:.5f}秒")
实例3:字典查找性能测试
import timeit
import random
setup = '''
import random
d = {i: str(i) for i in range(10000)}
keys = list(d.keys())
random.shuffle(keys)
'''
code = '''
for k in keys[:1000]:
val = d[k]
'''
t = timeit.timeit(code, setup=setup, number=100)
print(f"1000次字典查找执行100次平均耗时: {t/100:.6f}秒")
实例4:函数性能比较
import timeit
import math
# 定义两种计算平方根的方法
def sqrt_math(x):
return math.sqrt(x)
def sqrt_op(x):
return x ** 0.5
# 比较性能
math_time = timeit.timeit('sqrt_math(2)',
setup='from __main__ import sqrt_math',
number=1000000)
op_time = timeit.timeit('sqrt_op(2)',
setup='from __main__ import sqrt_op',
number=1000000)
print(f"math.sqrt: {math_time:.5f}秒")
print(f"**运算符: {op_time:.5f}秒")
print(f"性能差异: {(op_time/math_time):.2f}倍")
实例5:类方法调用开销
import timeit
class TestClass:
def instance_method(self):
pass
@classmethod
def class_method(cls):
pass
@staticmethod
def static_method():
pass
# 测试不同方法的调用开销
instance_time = timeit.timeit('obj.instance_method()',
setup='from __main__ import TestClass; obj=TestClass()',
number=1000000)
class_time = timeit.timeit('TestClass.class_method()',
setup='from __main__ import TestClass',
number=1000000)
static_time = timeit.timeit('TestClass.static_method()',
setup='from __main__ import TestClass',
number=1000000)
print(f"实例方法: {instance_time:.5f}秒")
print(f"类方法: {class_time:.5f}秒")
print(f"静态方法: {static_time:.5f}秒")
实例6:大数据结构操作性能
import timeit
import numpy as np
setup = '''
import numpy as np
arr = np.random.rand(10000)
lst = list(arr)
'''
numpy_time = timeit.timeit('np.sum(arr)', setup=setup, number=1000)
list_time = timeit.timeit('sum(lst)', setup=setup, number=1000)
print(f"NumPy求和: {numpy_time:.5f}秒")
print(f"列表求和: {list_time:.5f}秒")
print(f"性能差异: {(list_time/numpy_time):.2f}倍")
实例7:文件I/O操作测试
import timeit
import tempfile
setup = '''
import tempfile
text = "Python timeit module examples\\n" * 1000
f = tempfile.NamedTemporaryFile(mode='w+')
'''
code = '''
f.write(text)
f.seek(0)
content = f.read()
'''
t = timeit.timeit(code, setup=setup, number=100, globals=globals())
print(f"100次文件写入读取平均耗时: {t/100:.4f}秒")
最佳实践提示
-
对于微小的代码片段,设置较大的
number
参数以获得更准确的结果 -
使用
setup
参数来初始化测试环境,避免将初始化时间计入测量 -
多次运行测试 (
repeat
) 并取最小值,以减少系统其他活动的影响 -
在比较两种实现时,确保它们在功能上是等价的
-
在实际应用中,考虑可读性和性能的平衡,不要过度优化
这些实例展示了 timeit
模块在各种场景下的应用,帮助开发者做出基于数据的性能优化决策。