IndexError只在实际访问索引时触发,因Python延迟检查;空列表下lst[-1]同样报错;推荐用try/except、if 0≤i<len(lst)或operator.itemgetter。

为什么IndexError: list index out of range总在访问索引时才报错
Python 列表不支持负向越界或超长正向索引,但不会提前拦截——它只在实际执行 my_list[i] 时才检查。也就是说,哪怕你写了 if i ,只要中间有并发修改、逻辑分支跳过判断、或者误把 <code>len() 当成“安全保证”,依然会崩。
常见踩坑点:
- 用
for i in range(len(lst)):循环,但循环体里删了元素,导致后续索引失效 - 多个条件用
and连接,但把长度检查写在后面,比如lst[i] and len(lst) > i—— Python 短路求值,lst[i]先执行就炸了 - 把
len(lst) == 0当成唯一判断依据,却忘了空列表下lst[-1]同样触发 IndexError
安全访问单个索引的三种写法(按推荐顺序)
别总想着“先检查再取值”,优先用更健壮的表达方式:
- 用
try/except直接捕获:适合索引来源不可控(如用户输入、配置项解析),且失败是预期场景之一try: value = my_list[idx] except IndexError: value = default_value - 用
if显式检查,但必须把长度判断放最前面,且注意符号:if 0 (支持负索引?不行,<code>-1虽合法但-1 恒真,得单独处理) - 用切片代替索引:切片越界不报错,返回空列表,适合“取一个默认值”场景
value = (my_list[idx:idx+1] or [default])[0],但注意这会多一次小对象分配
遍历列表时动态修改导致的 IndexError 怎么避免
这不是索引计算错,而是列表结构变了。典型错误:for i in range(len(lst)): 配合 lst.pop(i) 或 del lst[i]。
立即学习“Python免费学习笔记(深入)”;
- 根本原因:
range在循环开始时就固定了上界,但pop()让后续元素前移,导致跳过元素或越界 - 正确做法:反向遍历(
for i in range(len(lst)-1, -1, -1)),或用列表推导式重建,或用while+pop(0)(仅当必须顺序处理) - 更推荐:别边遍历边改原列表。先收集要删的索引或元素,循环结束后统一处理,比如:
to_remove = [i for i, x in enumerate(my_list) if condition(x)] for i in reversed(to_remove): del my_list[i]
用 numpy 或 pandas 时 IndexError 的特殊表现
它们的索引机制和 Python 原生不同,但错误信息一样,容易误导:
-
numpy.ndarray支持布尔索引、花式索引,但a[100]在长度不足时仍报IndexError;不过a[[1,2,100]]会直接崩,而a[np.array([1,2,100])]也是同样行为 -
pandas.Series和DataFrame默认用标签索引(.loc),但用整数位置索引(.iloc)时,规则和原生 list 一致:越界就报IndexError - 关键区别:pandas 的
.iloc[100]报错,但.loc[100]可能返回NaN(如果标签 100 不存在)——别混用.loc和.iloc当兜底方案
def f(items=[], idx=0),多次调用后 items 是同一个可变对象,len(items) 不再反映初始状态。这种隐式状态比索引越界更难定位。


















