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 模块在各种场景下的应用,帮助开发者做出基于数据的性能优化决策。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值