易君召
发布于 2026-09-13 / 作者:易君召 / 2 阅读
0

Python 代码性能优化技巧

原则:先定位瓶颈,再优化。不要盲目提前优化,用 cProfile / line_profiler 找出耗时代码,再下手。

一、基础语法层面(低成本见效快)

  1. 优先使用内置类型与内置函数 Python 内置(list/dict/set)底层是 C 实现,速度远快于自己用 Python 循环实现。

    • 集合set做成员判断 x in set,O (1);列表x in list是 O (n)

    • sum(), map(), sorted() 代替手写 for 循环累加

  2. 减少循环内的重复计算 循环里面不要反复查询属性、函数调用。

    # 慢
    for item in data:
        val = item.attr * math.sqrt(100)
    
    # 快:把不变计算提到循环外
    sqrt100 = math.sqrt(100)
    for item in data:
        val = item.attr * sqrt100
    
  3. 列表推导式 > for append 循环 列表推导式底层 C 执行,比循环里反复list.append更快。

    res = [x*2 for x in data]
    

    超大数据用生成器表达式 (x*2 for x in data),节省内存,避免一次性生成大列表。

  4. 局部变量访问比全局变量更快 局部变量存在固定索引数组,全局需要字典查找。

    # 优化:把全局函数/变量引入函数局部
    import math
    def calc(data):
        sqrt = math.sqrt
        return [sqrt(x) for x in data]
    
  5. 字符串拼接不要用 += 在循环里 Python 字符串不可变,s += xxx会不断新建字符串。

    • 少量拼接可用 f-string;大量拼接用str.join()

    parts = []
    for s in str_list:
        parts.append(s)
    result = ''.join(parts)
    

二、数据结构选型

  • 查找、去重 → set

  • 键值查找 → dict;有序映射用 collections.OrderedDict(py3.7 + 普通 dict 默认保序)

  • 频繁追加弹出两端 → collections.deque(O (1),list pop (0) 是 O (n))

  • 多维数值计算:放弃原生 list,用 numpy 数组,向量化运算代替 Python 循环,巨大提升。

三、循环与计算加速

  1. 向量化(NumPy / Pandas) 把循环从 Python 解释器下沉到 C 层,尽量避免 for 遍历数组

    import numpy as np
    arr = np.array([1,2,3])
    res = arr * 2  # 无Python循环
    
  2. 使用内置模块:itertools itertools都是 C 实现,适合迭代组合、笛卡尔积、分组等场景,节省内存 + 速度快。

    import itertools
    for a,b in itertools.product(list1, list2):
        ...
    
  3. JIT 即时编译:numba 适合数值密集循环,加装饰器即可把 Python 函数编译成机器码,改动极小。

    from numba import jit
    
    @jit(nopython=True)
    def heavy_calc(arr):
        s = 0
        for x in arr:
            s += x**2
        return s
    

    限制:nopython 模式不能大量调用 Python 对象。

  4. C 扩展方案(重度优化)

    • Cython:Python-like 语法编译为 C,适合复杂循环

    • C/C++ 写扩展,或用 ctypes/cffi 调用已有 C 库

四、IO 优化(IO 往往是最大瓶颈)

IO 瓶颈优先于 CPU 优化:

  1. 文件读写:一次性读写大块,不要逐行频繁 readline 小 IO

  2. 使用上下文管理器 with open(...),自动管理句柄

  3. 网络 IO:异步 asyncio,并发请求代替串行;连接复用(http session)

  4. 大量磁盘读写考虑缓冲、批量提交,减少系统调用

五、垃圾回收 & 内存优化

  1. 大对象用完及时解除引用 del obj,帮助 GC 回收

  2. __slots__:类实例属性固定时,关闭实例__dict__,减少内存占用

class User:
    __slots__ = ["id", "name"]  # 不再创建dict
    def __init__(self, id, name):
        self.id = id
        self.name = name
  1. 避免循环引用,循环引用会让 GC 无法及时回收

六、并发 / 并行注意坑(Python GIL)

GIL:同一时刻一个 Python 进程只有一个线程执行 Python 字节码。

  • CPU 密集任务:多线程几乎无加速,用 multiprocessing /joblib 多进程

  • IO 密集任务(网络、文件):多线程 /asyncio 效果很好,等待时释放 GIL

  • 进程有创建开销,任务粒度不能太小

七、性能分析工具

# cProfile 统计函数耗时
python -m cProfile -s cumulative your_script.py

# line_profiler 逐行耗时(pip install line-profiler)
# 函数上加 @profile 装饰器
kernprof -l -v your_script.py

八、避坑清单

  • ❌ 不要在循环里导入模块(import 放到文件顶部)

  • ❌ 不要用 eval/exec 做计算,很慢且不安全

  • ❌ 不要大量动态属性 obj.__dict__["key"],属性查找慢

  • ❌ 递归深度大时,Python 递归开销高,且有递归上限,改成循环

优先级总结

  1. 算法优化(降低时间复杂度,收益最大,比如 O (n²)→O (n log n))

  2. 数据结构选型

  3. 减少循环内重复计算、改用向量化

  4. Numba/Cython 加速热点循环

  5. IO / 并发优化

  6. 语法细节微调


本文原创作者:易君召,详见:https://www.yijunzhao.cn/authors/yijunzhao,转载请注明出处。

原文链接 https://www.yijunzhao.cn/archives/python-code-performance-optimization-tips

欢迎访问 小易撩挨踢

https://www.yijunzhao.cn/