Python精选200Tips:101-105

继续挑Python自带的家伙事儿

运行系统:macOS Sonoma 14.6.1
Python编译器:PyCharm 2024.1.4 (Community Edition)
Python版本:3.12

往期链接:

1-5 6-10 11-20 21-30 31-40 41-50
51-60:函数 61-70:类 71-80:编程范式及设计模式
81-90:Python编码规范 91-100:Python自带常用模块-1

101 timeit:测量代码执行时间

timeit 模块是 Python 用于测量代码执行时间的标准库。它的设计目的是为了提供精确的时间测量,尤其是在对小段代码进行性能分析时。主要特点

  • 高精度计时: timeit 模块通过多次执行代码来减少由于系统负载等外部因素造成的误差。
  • 自动化执行: 它可以自动运行指定次数的代码,减少手动计时的繁琐。
  • 灵活性: 可以在不同的上下文中使用,支持单独执行的代码段。
  1. timeit.timeit(stmt, setup, number)

参数:

  • stmt: 字符串或可调用对象要测量的代码段。可以是一个 Python 语句的字符串,也可以是一个可调用的函数。如果是字符串,timeit 会将其执行多次。
  • setup: 设定代码,通常用于导入模块或定义变量,默认是空字符串。
  • number: 指定 stmt 被执行的次数,默认值是 1,000,000。
  • 返回值: 返回执行 stmt 的总时间(以秒为单位)。
import timeit

# 测试代码
code_to_test = """
a = range(1000)
sum(a)
"""

# 测量时间
execution_time = timeit.timeit(code_to_test, number=10000)
print(f"执行时间: {
     execution_time:.5f} 秒")
# 输出:执行时间: 0.07915 秒
  1. timeit.repeat(stmt, setup, repeat, number)

参数:

  • stmt: 字符串或可调用对象。同 timeit() 中的 stmt,要测量的代码段。
  • setup: 设定代码。
  • repeat: 执行 timeit 测量的次数,返回一个列表。
  • number: 指定 stmt 被执行的次数。
  • 返回值: 返回一个列表,其中包含多次测量的执行时间。
import timeit

# 测量时间重复执行
execution_times = timeit.repeat(stmt="sum(range(1000))", repeat=5, number=10000)
print(f"执行时间: {
     execution_times}")
# 输出 执行时间: [0.08649416698608547, 0.07826487498823553, 0.07675112498691306, 0.07559383401530795, 0.07525045800139196]

3 示例:比较字符串连接的效率

比较使用 + 运算符和 join() 方法连接字符串的性能。通常,使用 join() 方法更为高效。

import timeit

# 方法1: 使用 + 运算符连接字符串
def concat_with_plus():
    result = ""
    for i in range(1000):
        result += str(i)
    return result

# 方法2: 使用 join() 方法连接字符串
def concat_with_join():
    result = "".join(str(i) for i in range(1000))
    return result

# 测量执行时间
plus_time = timeit.timeit(concat_with_plus, number=10000)
join_time = timeit.timeit(concat_with_join, number=10000)

print(f"使用 + 运算符连接字符串执行时间: {
     plus_time:.5f} 秒")  # 输出: 使用 + 运算符连接字符串执行时间: 0.74197 秒
print(f"使用 join() 方法连接字符串执行时间: {
     join_time:.5f} 秒")  # 输出: 使用 join() 方法连接字符串执行时间: 0.59136 秒

4 示例:比较斐波那契数列的计算方法

import timeit

# 递归方法
def fibonacci_recursive(n):
    if n <= 1:
        return n
    return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)

# 动态规划方法
def fibonacci_dp(n):
    if n <= 1:
        return n
    fib = [0] * (n + 1)
    fib[1] = 1
    for i in range(2, n + 1):
        fib[i] = fib[i - 1] + fib[i - 2]
    return fib[n]

# 测量执行时间
n = 35  # 计算第35个斐波那契数
recursive_time = timeit.timeit(lambda: fibonacci_recursive(n), number=10)
dp_time = timeit.timeit(lambda: fibonacci_dp(n), number=10)

print(f"递归方法执行时间: {
     recursive_time:.5f} 秒")  # 输出: 递归方法执行时间: 7.95062 秒
print(f"动态规划方法执行时间: {
     dp_time:.5f} 秒")  # 输出: 动态规划方法执行时间: 0.00002 秒

102 profile: 程序性能分析工具

profile 模块是 Python 的一个内置模块,用于进行性能分析。它可以分析 Python 程序的运行时间,并提供详细的报告,以帮助开发者识别性能瓶颈。模块说明:

  • 主要功能: profile 提供了一个简单的接口来跟踪程序的执行,并生成执行统计信息,帮助开发者优化代码。
  • 输出格式: profile 可以生成多种格式的报告,包括文本和图形格式。
  • 使用方式: 可以通过命令行或在代码中调用。

主要类和方法:

  • Profile: 主要的分析器类,用于创建性能分析对象。
  • run(statement): 运行给定的代码段并分析其性能。
  • print_stats(): 打印性能分析报告。

1 示例:分析计算斐波那契数列的程序

import profile

def fibonacci_recursive(n):
    if n <= 1:
        return n
    return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)

def main():
    n = 30  # 计算第30个斐波那契数
    result = fibonacci_recursive(n)
    print(f"Fibonacci({
     n}) = {
     result}")

# 使用 profile 模块分析性能
if __name__ == "__main__":
    profile.run('main()')

输出

Fibonacci(30) = 832040
         2692543 function calls (7 primitive calls) in 2.100 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.089    2.089 :0(exec)
        1    0.000    0.000    0.000    0.000 :0(print)
        1    0.011    0.011    0.011    0.011 :0(setprofile)
        1    0.000    0.000    2.089    2.089 <string>:1(<module>)
2692537/1    2.089    0.000    2.089    2.089 all_oneline_python.py:3(fibonacci_recursive)
        1    0.000    0.000    2.089    2.089 all_oneline_python.py:8(main)
        1    0.000    0.000    2.100    2.100 profile:0(main())
        0    0.000             0.000          profile:0(profiler)

输出字段说明:

  • ncalls: 函数被调用的次数。
  • tottime: 函数自身的总执行时间(不包括子函数调用的时间)。
  • percall: 每次调用的平均时间(tottime 除以 ncalls)。
  • cumtime: 函数及其所有被调用函数的总执行时间。
  • percall: 每次调用的平均时间(cumtime 除以 ncalls)。
  • filename:lineno(function): 函数所在的文件和行号。

查看程序的性能瓶颈:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AnFany

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值