Python 优化 在 跳过 这一步 时 失败

发布: (2025年12月20日 GMT+8 14:35)
5 min read
原文: Dev.to

抱歉,我需要您提供要翻译的完整文本(除代码块和 URL 之外的内容),才能为您进行翻译。请把文章的正文粘贴在这里,我会按照要求保留源链接并保持原有的格式进行翻译。

大多数开发者面临的问题

你注意到你的 Python 脚本运行缓慢。你已经阅读了关于优化的文章。你知道列表推导式比循环更快。你听说 NumPy 很快。所以你开始重写代码。

问题出在哪里:你是基于假设而不是数据进行优化的。

每个人都会跳过的那一步

在优化之前先进行性能分析。
大家都这么说,但大多数开发者(包括过去的我)直接跳到优化阶段。

一个改变我方法的真实案例

def process_sales_data(filename):
    df = pd.read_csv(filename)
    # Calculate profit for each row
    profits = []
    for index, row in df.iterrows():
        profit = row['revenue'] - row['cost']
        profits.append(profit)
    df['profit'] = profits

    # Filter and group
    profitable = df[df['profit'] > 100]
    averages = profitable.groupby('region')['profit'].mean()

    return averages

处理 100,000 行耗时 42 秒 —— 太慢了。

性能分析揭示的内容

import cProfile
import pstats
from io import StringIO

profiler = cProfile.Profile()
profiler.enable()

process_sales_data('sales.csv')

profiler.disable()
stream = StringIO()
stats = pstats.Stats(profiler, stream=stream)
stats.sort_stats('cumulative')
stats.print_stats(20)

print(stream.getvalue())

输出让我大吃一惊:

  • iterrows() 循环消耗了 90 % 的运行时间。
  • 我担心的 groupby?仅占 2 %

修复很简单

def process_sales_data(filename):
    df = pd.read_csv(filename)

    # Vectorized operation – no loop
    df['profit'] = df['revenue'] - df['cost']

    # Same filtering and grouping
    profitable = df[df['profit'] > 100]
    averages = profitable.groupby('region')['profit'].mean()

    return averages

运行时间从 42 秒 降至 1.2 秒 – 通过更改三行代码实现了 35× 的加速。

为什么我们的直觉会失效

  • 我们关注语法,而不是执行成本。 嵌套循环看起来很慢,但如果它们只在 10 条数据上运行一次,那就无关紧要。一次处理 100,000 条数据的函数调用更值得关注。
  • 我们低估了 Python 的开销。 在 pandas 中逐行迭代会产生巨大的开销;看似简单的操作会触发成千上万的操作。
  • 我们认为最近的更改导致了慢速。 通常慢速一直存在,只是我们在数据规模扩大后才注意到。
  • 我们优化我们理解的部分。 我理解分组操作,所以把注意力放在那里。真正的问题是我没有考虑到的东西。

如何正确进行性能分析

import cProfile
import pstats

profiler = cProfile.Profile()
profiler.enable()

your_function()

profiler.disable()

stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')  # Sort by total time including calls
stats.print_stats(20)           # Show top 20 functions

首先查看 cumtime 列。它表示包括嵌套调用在内的总时间。cumtime 最高的函数就是你的主要目标。

我现在遵循的模式

  1. 测量基准性能 – 对完整操作计时。
  2. 分析找出瓶颈 – 使用 cProfile,而不是凭猜测。
  3. 优化最主要的瓶颈 – 修复实际消耗时间的部分。
  4. 再次测量 – 验证改进效果。
  5. 如有必要重复 – 再次分析以发现下一个瓶颈。

这种系统化的方法每次都能胜过直觉。

常见的性能分析发现

  • 数据库查询消耗 80 %+ 的运行时间(优化查询,而不是 Python 代码)。
  • 文件 I/O 主导数据处理脚本(使用缓冲操作,采用二进制格式)。
  • pandas 中逐行迭代会产生巨大的开销(全部向量化)。
  • 循环中的字符串拼接导致 O(n²) 行为(改用 ''.join())。
  • 不必要的对象创建会增加垃圾回收压力(复用缓冲区)。

仅凭阅读代码是找不到这些问题的。只有通过性能分析才能发现。

课程

在花费数小时优化 Python 代码之前:

  • 不要根据博客文章重写已工作的代码。
  • 不要假设自己知道慢的部分。
  • 不要一次优化多件事。
  • 不要跳过测量。

先进行剖析。 每次都要。


想深入了解 Python 优化吗? 查看完整指南:Python Optimization Guide: How to Write Faster, Smarter Code.

Back to Blog

相关文章

阅读更多 »