提前优化让代码更难改,如滥用缓存、过早替换数据结构、盲目省内存等反而增加维护成本;应先用 cprofile 定位真实瓶颈,优先升级依赖而非手写优化,并重视类型提示与 slots 的适用场景。

提前优化让代码更难改
很多人在写 Python 时,一看到“性能差”就急着加缓存、换数据结构、手写循环替代列表推导——结果是逻辑变绕、边界条件变多、后续改需求时不敢动那块代码。比如用 lru_cache 装了一个本该接收可变参数的函数,运行时报 TypeError: unhashable type: 'list',但错误堆栈根本看不出是缓存惹的祸。
- 缓存类优化(
@lru_cache、@cache)只适合纯函数:输入相同、输出确定、无副作用 - 过早引入
deque替代list做队列,反而让团队新人误以为所有插入都该用.appendleft() - 用
map()或生成器表达式强行“省内存”,却让调试时没法直接print(my_gen)看中间值
profile 之前别猜热点
没跑过 cProfile 就说“这个循环太慢”,大概率是在优化错的地方。真实项目里,90% 的性能瓶颈不在算法,而在 I/O、序列化、重复加载配置或 ORM 查询 N+1。
- 先跑一次
python -m cProfile -s cumtime your_script.py,盯住cumtime最高的几行,不是tottime -
line_profiler更准,但得加装饰器;别对整个模块加,只标疑似慢的函数,否则开销反超收益 - Web 场景下,
timeit测单行代码毫无意义——HTTP 延迟、数据库连接池、JSON 序列化才是大头
类型提示和静态检查不是性能工具
有人以为加了 typing.List[int] 或用 mypy 就能加速,其实完全不相关。Python 运行时根本忽略类型注解,它们只服务 IDE 和检查器。
- 加类型提示本身有成本:维护负担、泛型嵌套过深时
mypy检查变慢(尤其带TypedDict和Union) - 用
__slots__省内存?只有当类实例上万且属性固定时才值得,否则只是让继承和动态赋值变脆弱 - 把
dict换成dataclass+frozen=True?除非你真需要不可变语义,否则只是增加初始化开销
依赖升级比手写优化更常见效
很多“慢”其实是旧版本 bug 或缺失优化。比如 pandas 1.5 之前,.groupby().apply() 默认不走并行;requests 旧版 DNS 缓存策略差,导致高并发下大量 getaddrinfo 阻塞。
立即学习“Python免费学习笔记(深入)”;
- 先确认当前依赖版本:
pip list --outdated,重点看numpy、pandas、pydantic、httpx - 用
pip install --upgrade --force-reinstall package_name排除本地编译残留问题 - 升级后务必跑集成测试——有些优化会改变浮点精度或空值处理逻辑(比如
pandas 2.0对NaN的排序行为)
实际项目里,最常被忽略的是“优化后要不要删掉临时注释”。比如写了个 # TODO: benchmark this before prod,上线后没人回来看,半年后变成技术债盲区。










