应缓存len()结果以避免重复开销:当容器长度不变且循环次数≥1000时,用data_len = len(data)提前缓存;enumerate和zip可替代range(len());海象运算符:=适合单次条件判断。

len()在循环条件中反复调用会拖慢速度
Python 的 len() 确实是 O(1) 操作,但每次调用仍要经过名称查找、函数分派、对象方法调用(obj.__len__())三步。在 while 或 for 条件里反复执行,这些开销会累积——尤其当循环体本身很轻量时,len() 可能占到总耗时的 20% 以上。
while i :每次迭代都重新查 <code>len、再查data、再进__len__-
for i in range(len(data))::不仅重复调用len(),还额外生成一个整数列表(或 range 对象),且后续还要用data[i]再查一次索引 - 更隐蔽的是
if len(some_list) > 0:这类判断,如果出现在高频循环内,也值得缓存
什么时候必须提前缓存 len 结果
只要满足「容器长度在循环过程中不变」+「循环次数较多(比如 ≥ 1000)」,就该缓存。常见场景包括:
- 遍历列表/元组/字符串做索引访问(
data[i]) - 手写
while循环控制边界(如解析协议、滑动窗口) - 嵌套循环中,外层长度固定但被内层反复读取
- 自定义类实现了开销较大的
__len__(比如要遍历子结构计数)
缓存写法很简单:data_len = len(data) 放在循环前,之后所有地方用 data_len 替代 len(data)。
enumerate 和 zip 已经隐式帮你省了 len
如果你只是想同时拿到索引和值,或并行遍历多个序列,enumerate() 和 zip() 内部不依赖 len(),也不生成中间 range,它们直接用迭代器推进,天然规避了长度查询问题。
立即学习“Python免费学习笔记(深入)”;
- 要索引+值 → 用
for i, item in enumerate(data):,别写for i in range(len(data)): - 要配对两个等长列表 → 用
for a, b in zip(list_a, list_b):,别写for i in range(len(list_a)):再分别取list_a[i]和list_b[i] - 注意:
zip()在 Python 3 中返回迭代器,不会预计算长度;若需提前知道是否等长,才需要显式检查len()
海象运算符(:=)适合一次性 len 判断
如果只在某个条件里用一次 len(),又不想多声明变量污染作用域,:= 是更干净的选择。它把赋值和使用绑在一起,避免二次调用。
例如:if (n := len(my_list)) > 100: —— 这里 len(my_list) 只执行一次,n 仅在该 if 块内有效。比先写 n = len(my_list) 再 if n > 100: 更紧凑,也比 if len(my_list) > 100:(重复调用)更高效。
真正容易被忽略的是:缓存不是为了“让代码看起来快”,而是切断解释器重复查名、重复进方法的路径。哪怕 len() 本身很快,调用链上的动态查找成本,在循环里会被放大。



















