推荐用 enumerate 替代 range(len(...))遍历列表,因其更高效、可读;成员检查优先用 in 而非手写循环;过滤求和等场景用生成器表达式省内存;循环内不变表达式需提前提取。

用 enumerate 替代 range(len(...))
直接索引遍历列表时,range(len(my_list)) 看似直观,但会多一次 len() 调用、生成一个不必要的整数序列,且可读性差。Python 的 enumerate() 是专为此设计的内置函数,它返回 (index, item) 元组,底层用 C 实现,开销极小。
- ✅ 推荐写法:
for i, item in enumerate(my_list): - ❌ 避免写法:
for i in range(len(my_list)): item = my_list[i] - 注意:如果只需要索引(不取值),仍用
range(len(...))更轻量;但这种情况本身往往暗示逻辑可重构
提前用 in 检查成员存在性,别写循环手动找
判断某个值是否在容器中,90% 场景下不该手写 for 循环加 break。Python 容器的 __contains__ 方法(即 in 操作)对 set 和 dict 是 O(1),对 list 是 O(n),但底层用 C 实现,比纯 Python 循环快 3–5 倍。
- ✅ 正确姿势:
if x in my_set:(优先把查找目标转成set) - ❌ 过度优化:
found = False; for v in my_list: if v == x: found = True; break - 特别注意:
list上反复in查找,应先转set——my_set = set(my_list)的一次性开销远低于多次线性扫描
用生成器表达式替代 list 推导式做中间过滤
当循环只是为后续操作(如 sum()、any()、max())提供数据源,且不需要所有结果都驻留内存时,用生成器表达式(圆括号)能省下大量内存并可能提前终止。
- ✅ 内存友好:
sum(x * 2 for x in data if x > 0) - ❌ 浪费内存:
sum([x * 2 for x in data if x > 0])—— 先建完整列表再求和 - 关键区别:生成器表达式不支持索引或重复遍历;若需多次使用,才考虑转成
list或用itertools.tee() - 性能提示:
any()和all()天然配合生成器,遇到第一个True或False就停,效率极高
避免在循环内重复计算不变表达式
把循环外就能确定的值、函数调用、属性访问提出来,尤其是涉及模块导入、对象方法绑定、正则编译等高成本操作。
立即学习“Python免费学习笔记(深入)”;
- ✅ 提前提取:
pattern = re.compile(r'\d+'); for line in lines: pattern.search(line) - ❌ 重复执行:
for line in lines: re.compile(r'\d+').search(line)—— 每次都重新编译正则 - 常见陷阱:
for item in items: item.some_method()中,如果some_method是无参且返回相同结果,可提成cached_result = item.some_method() - 注意:Python 不会自动优化循环内未变化的变量引用,哪怕看起来“显然不变”
真正卡顿的循环,往往不是算法复杂度问题,而是混进了隐式 I/O、重复对象创建、或没意识到某些操作本可在循环外固化。动手前先看三眼:这个计算真的必须在每次迭代里做吗?










