indexerror发生在对序列类型(list、tuple、str、bytes)越界索引访问时,如my_list[10]或"hello"[10];keyerror则在字典等映射类型中访问不存在的键时触发,如my_dict["missing_key"]。

IndexError发生在哪些具体操作上
只要对序列类型(list、tuple、str、bytes)做越界索引访问,就立刻抛 IndexError。它不看内容,只看下标是否在 [0, len(obj)) 范围内,负数索引也受同样规则约束(即不能小于 -len(obj))。
常见触发点:
-
my_list[10]—— 列表只有 5 个元素 -
"hello"[10]—— 字符串长度为 5,索引 10 越界 -
my_tuple[-100]—— 负索引超出可接受范围 -
arr[0][5]—— 二维结构中内层序列越界,外层没问题但内层报IndexError
注意:IndexError 不会在切片时抛出(如 my_list[10:20] 返回空列表),这是设计使然,也是容易忽略的差异点。
KeyError通常在什么上下文中出现
KeyError 是映射类型(主要是 dict,还有 collections.defaultdict 在未设默认值时、json.loads() 后的字典访问等)对不存在的键进行索引访问时抛出。它和“是否存在”强相关,和“顺序”“长度”无关。
典型场景:
-
my_dict["missing_key"]—— 直接用中括号取不存在的键 -
config["database"]["host"]—— 嵌套字典中某一层缺失键(第二层"host"找不到) -
os.environ["MISSING_VAR"]—— 环境变量未设置时访问 -
json_data["items"][0]["id"]—— JSON 解析后结构不稳定,任意一环为空或缺字段
对比:用 .get() 或 in 判断可避免 KeyError,但无法绕过 IndexError 的边界检查逻辑。
为什么KeyError在实际项目中更频繁遇到
不是因为语言设计偏爱它,而是因为数据来源不可控。API 响应、配置文件、用户输入、数据库查询结果,绝大多数以字典/JSON 形式流动,而这些结构天然稀疏、字段可选、版本易变。
几个现实因素放大了 KeyError 出现概率:
- 前后端字段约定失效(比如后端删了一个字段,前端代码没同步更新)
- 第三方 SDK 返回结构随版本变化,文档滞后
-
**kwargs传参时漏传可选键,函数内部直接params["timeout"] - 用
dict模拟对象状态(如{"status": "pending", "result": None}),但后续分支逻辑假设某个键一定存在
而 IndexError 多出现在明确控制长度的本地计算中(如循环处理固定结构的 CSV 行、矩阵运算),更容易被单元测试覆盖。
如何快速区分并稳妥处理这两类异常
看错误信息里的关键词最直接:list index out of range 或 string index out of range → IndexError;KeyError: 'xxx' → KeyError。但更关键的是根据容器类型预判——拿到一个变量,先确认它是 list 还是 dict,再决定用 len()/range() 还是 in/.get()。
实用建议:
- 对序列:优先用
for item in seq:避免索引;必须索引时,加if i 或用 <code>try/except IndexError: - 对映射:默认用
.get(key, default);需要严格校验时,显式写if key not in d: raise ValueError(...),而不是依赖KeyError做流程控制 - 嵌套访问(如
d["a"]["b"]["c"])极易崩溃,改用from operator import itemgetter; itemgetter("a", "b", "c")(d)不行,得用d.get("a", {}).get("b", {}).get("c")或专用工具如dictor库
真正麻烦的不是单层异常,而是多层混合结构里,IndexError 和 KeyError 可能交替出现——比如 data[0]["items"][5]["name"],错在哪个位置,光看堆栈不够,得结合数据样本逐层 inspect。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











