4.13 Python3 timeit 模块:性能度量工具

timeit 模块是 Python 标准库中用于测量小段代码执行时间的工具,特别适合比较不同实现方式的性能差异。


目录

1.基本用法

1.1 命令行使用

1.2 Python 程序中使用

2. 主要函数

3. 示例

3.1 比较两种字符串连接方式的性能

​编辑

3.2 测量函数执行时间

4. 最佳实践

5. 高级用法

5.1 使用 Timer 类

5.2 在 Jupyter Notebook 中使用

实例1:比较列表创建方式的性能

实例2:字符串格式化方法比较

实例3:字典查找性能测试

实例4:函数性能比较

实例5:类方法调用开销

实例6:大数据结构操作性能

实例7:文件I/O操作测试

最佳实践提示


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. 主要函数

  1. timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)

    • stmt: 要测量的代码语句

    • setup: 执行前的初始化代码

    • number: 执行次数

    • 返回执行的总时间(秒)

  2. timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000)

    • 重复测量多次,返回时间列表

  3. 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. 最佳实践

  1. 多次测量:使用 repeat() 多次测量取最小值,减少系统波动影响

  2. 合适的大小:选择适当的 number 参数,使总时间在 0.2-2 秒之间

  3. 避免副作用:确保被测代码没有副作用,或每次测试前重置状态

  4. 使用 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}秒")

最佳实践提示

  1. 对于微小的代码片段,设置较大的 number 参数以获得更准确的结果

  2. 使用 setup 参数来初始化测试环境,避免将初始化时间计入测量

  3. 多次运行测试 (repeat) 并取最小值,以减少系统其他活动的影响

  4. 在比较两种实现时,确保它们在功能上是等价的

  5. 在实际应用中,考虑可读性和性能的平衡,不要过度优化

这些实例展示了 timeit 模块在各种场景下的应用,帮助开发者做出基于数据的性能优化决策。


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值