原则:先定位瓶颈,再优化。不要盲目提前优化,用
cProfile/line_profiler找出耗时代码,再下手。
一、基础语法层面(低成本见效快)
优先使用内置类型与内置函数 Python 内置(
list/dict/set)底层是 C 实现,速度远快于自己用 Python 循环实现。集合
set做成员判断x in set,O (1);列表x in list是 O (n)用
sum(),map(),sorted()代替手写 for 循环累加
减少循环内的重复计算 循环里面不要反复查询属性、函数调用。
# 慢 for item in data: val = item.attr * math.sqrt(100) # 快:把不变计算提到循环外 sqrt100 = math.sqrt(100) for item in data: val = item.attr * sqrt100列表推导式 > for append 循环 列表推导式底层 C 执行,比循环里反复
list.append更快。res = [x*2 for x in data]超大数据用生成器表达式
(x*2 for x in data),节省内存,避免一次性生成大列表。局部变量访问比全局变量更快 局部变量存在固定索引数组,全局需要字典查找。
# 优化:把全局函数/变量引入函数局部 import math def calc(data): sqrt = math.sqrt return [sqrt(x) for x in data]字符串拼接不要用
+=在循环里 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 循环,巨大提升。
三、循环与计算加速
向量化(NumPy / Pandas) 把循环从 Python 解释器下沉到 C 层,尽量避免 for 遍历数组
import numpy as np arr = np.array([1,2,3]) res = arr * 2 # 无Python循环使用内置模块:itertools
itertools都是 C 实现,适合迭代组合、笛卡尔积、分组等场景,节省内存 + 速度快。import itertools for a,b in itertools.product(list1, list2): ...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 对象。
C 扩展方案(重度优化)
Cython:Python-like 语法编译为 C,适合复杂循环
C/C++ 写扩展,或用 ctypes/cffi 调用已有 C 库
四、IO 优化(IO 往往是最大瓶颈)
IO 瓶颈优先于 CPU 优化:
文件读写:一次性读写大块,不要逐行频繁 readline 小 IO
使用上下文管理器
with open(...),自动管理句柄网络 IO:异步
asyncio,并发请求代替串行;连接复用(http session)大量磁盘读写考虑缓冲、批量提交,减少系统调用
五、垃圾回收 & 内存优化
大对象用完及时解除引用
del obj,帮助 GC 回收__slots__:类实例属性固定时,关闭实例__dict__,减少内存占用
class User:
__slots__ = ["id", "name"] # 不再创建dict
def __init__(self, id, name):
self.id = id
self.name = name
避免循环引用,循环引用会让 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 递归开销高,且有递归上限,改成循环
优先级总结
算法优化(降低时间复杂度,收益最大,比如 O (n²)→O (n log n))
数据结构选型
减少循环内重复计算、改用向量化
Numba/Cython 加速热点循环
IO / 并发优化
语法细节微调
本文原创作者:易君召,详见:https://www.yijunzhao.cn/authors/yijunzhao,转载请注明出处。
原文链接
欢迎访问 小易撩挨踢