先用cProfile和snakeviz定位性能瓶颈,再针对性优化:字符串拼接用join、查找用set、小数据不用numpy、减少全局变量访问;计算密集型用NumPy/多进程/Cython,I/O密集型用asyncio/线程,善用lru_cache缓存。

python代码跑得慢,别急着重写,先搞清楚瓶颈在哪。性能问题90%出在不该用Python的地方,或者用了低效写法,而不是语言本身慢。
先定位:别猜,用工具看哪里卡
盲目优化等于浪费时间。Python自带cProfile就能快速抓出耗时大户:
- 加一行
python -m cProfile -s cumulative your_script.py,按累计时间排序,一眼看到哪几个函数吃掉最多CPU - 配合
snakeviz(pip install snakeviz)可视化:python -m cProfile -o profile.out your_script.py && snakeviz profile.out,生成交互式火焰图,调用链和耗时分布一目了然 - 内存不是瓶颈?也别忽略——用
memory_profiler查谁在疯狂分配对象:@profile装饰函数,再运行python -m memory_profiler your_script.py
常见拖慢元凶:这些写法看着简单,其实很贵
很多“Pythonic”写法在数据量大时反而成负担:
- 循环里拼字符串:用
''.join(list_of_str)代替s += 'x',后者每次创建新对象,O(n²)变O(n) - 反复查列表/字符串:用
if x in set_x:代替if x in list_x:,查找从O(n)降到O(1) - 小数据用NumPy/pandas反而是累赘:几十个数就别上DataFrame,纯Python列表+内置函数(
sum()、max())更快 - 全局变量读写频繁:函数内多用局部变量,避免每次访问都查全局命名空间
该提速时就提速:不硬扛,借力更高效
真遇到计算密集型任务,别死守纯Python:
立即学习“Python免费学习笔记(深入)”;
- 数值计算优先用
NumPy向量化,比for循环快几十到几百倍;矩阵运算直接上scipy - I/O密集?用
asyncio或concurrent.futures并行,但注意GIL限制——CPU密集型选multiprocessing,I/O密集型选threading或asyncio - 关键路径函数太慢?用
Cython或numba.jit编译加速,几行装饰器就能让循环飞起来 - 重复计算?加
@functools.lru_cache()缓存结果,尤其适合递归或参数有限的函数
别忘底层:有时候慢跟代码无关
环境和依赖也可能拖后腿:
- 确认用的是CPython最新稳定版(如3.11+),新版对字节码和解释器做了不少优化
- 检查是否启用了调试模式(
python -O或-OO可去掉assert和文档字符串,小幅提速) - 第三方库版本老旧?比如旧版
requests或SQLAlchemy可能有已知性能缺陷,升级常有惊喜 - 磁盘IO慢?把日志级别调高(比如从DEBUG改成INFO),减少不必要的文件写入
不复杂但容易忽略。找准瓶颈,改对地方,Python照样能跑得又稳又快。