什么是 KeyError?
KeyError 是 Python 中的一种异常(Exception),当你尝试访问一个字典中不存在的键时,Python 就会抛出这个错误。

可以把字典想象成一个现实中的字典或者电话簿,你通过“单词”(键)来查找它的“解释”(值),如果你查一个字典里根本没有的单词,会发生什么?你会找不到。KeyError 就是编程世界里的“找不到”这个情况。
KeyError = 尝试获取一个不存在的键。
何时会发生 KeyError?
最常见的场景有以下几种:
直接使用方括号 [] 访问
这是最直接也是最容易出现 KeyError 的方式。

my_dict = {'name': 'Alice', 'age': 30}
# 访问存在的键,没问题
print(my_dict['name']) # 输出: Alice
# 访问不存在的键,会抛出 KeyError
try:
print(my_dict['city'])
except KeyError as e:
print(f"捕获到错误: {e}")
# 输出: 捕获到错误: 'city'
在 for 循环中访问一个可能不存在的键
如果你不确定某个键是否存在,并且在循环中直接使用 [] 访问,也容易出错。
data = {'user1': {'id': 101}, 'user2': {'id': 102}}
for username in ['user1', 'user2', 'user3']:
# user3 不在 data 字典中,这行代码会抛出 KeyError
user_info = data[username]
print(f"用户 {username} 的ID是: {user_info['id']}")
使用 dict.get() 但没有提供默认值
dict.get() 方法本身是安全的,不会抛出 KeyError,但如果开发者错误地认为它和 [] 一样,可能会在后续操作中导致问题。
my_dict = {'a': 1, 'b': 2}
# get() 方法在键不存在时返回 None,不会报错
value = my_dict.get('c')
print(f"获取到的值是: {value}") # 输出: 获取到的值是: None
# 如果开发者直接对 None 进行操作,可能会引发其他错误
# 尝试对 None 进行加法运算
try:
result = value + 10
except TypeError as e:
print(f"捕获到错误: {e}")
# 输出: 捕获到错误: unsupported operand type(s) for +: 'NoneType' and 'int'
虽然这不是 KeyError,但它是一个相关的、因处理缺失键而引发的常见问题。
如何避免和处理 KeyError?
处理 KeyError 的核心思想是:在访问键之前,先检查它是否存在,或者使用更安全的方法来获取值。
这里有几种非常实用的方法:
使用 in 关键字进行安全检查(推荐)
这是最直观、最易读的方法,先判断键是否在字典中,再决定如何操作。
my_dict = {'name': 'Alice', 'age': 30}
key_to_check = 'city'
if key_to_check in my_dict:
print(f"{key_to_check} 的值是: {my_dict[key_to_check]}")
else:
print(f"字典中不存在键: {key_to_check}")
# 输出: 字典中不存在键: city
使用 dict.get() 方法(强烈推荐)
dict.get(key, default_value) 是获取字典值最安全、最 Pythonic 的方式。
key存在,返回对应的value。key不存在,返回你提供的default_value(默认为None),并且不会抛出KeyError。
my_dict = {'name': 'Alice', 'age': 30}
# 安全地获取 'city' 的值,如果不存在,则返回 'Unknown'
city = my_dict.get('city', 'Unknown')
print(f"城市是: {city}") # 输出: 城市是: Unknown
# 如果不提供默认值,会返回 None
country = my_dict.get('country')
print(f"国家是: {country}") # 输出: 国家是: None
使用 try...except 块捕获异常
如果你预期某个键可能不存在,并且希望在它不存在时执行特定的逻辑(而不是简单地提供一个默认值),try...except 是一个很好的选择,这通常用于处理“键存在是常态,不存在是异常情况”的场景。
my_dict = {'name': 'Alice', 'age': 30}
try:
# 尝试获取 'city' 的值
city = my_dict['city']
print(f"城市是: {city}")
except KeyError:
# 如果捕获到 KeyError,执行这里的代码
print("警告:'city' 键不存在,将使用默认设置。")
city = '默认城市'
print(f"已设置城市为: {city}")
使用 dict.setdefault() 方法
setdefault(key, default_value) 有两个作用:
key存在,返回它对应的value(和get一样)。key不存在,它会将key: default_value这对键值添加到字典中,然后再返回default_value。
当你想在获取一个可能不存在的键的同时,确保这个键被初始化时,这个方法非常有用。
my_dict = {'name': 'Alice', 'age': 30}
# 尝试获取 'score',如果不存在,则设置为 0 并返回 0
score = my_dict.setdefault('score', 0)
print(f"分数是: {score}") # 输出: 分数是: 0
print(f"更新后的字典: {my_dict}") # 输出: 更新后的字典: {'name': 'Alice', 'age': 30, 'score': 0}
总结与最佳实践
| 方法 | 描述 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
dict[key] |
直接访问 | 语法简洁 | 键不存在时抛出 KeyError |
当你100%确定键一定存在时。 |
key in dict |
先检查,后访问 | 逻辑清晰,易读 | 需要两行代码,稍显冗长 | 通用场景,特别是需要根据键是否存在执行不同逻辑时。 |
dict.get(key, default) |
安全获取 | 最推荐,简洁、安全、Pythonic | 无法区分“键不存在”和“键存在但值为 None” |
绝大多数情况下的首选,当你需要一个默认值或安全地获取值时。 |
try...except KeyError |
捕获异常 | 处理“异常情况”的逻辑非常优雅 | 代码块稍大,可能被认为是“防御式编程” | 当键不存在是“异常”而非“常态”,且需要复杂处理时。 |
dict.setdefault(key, default) |
获取并设置默认值 | 一举两得,能初始化字典 | 会修改原字典 | 当你不仅需要获取值,还需要在不存时初始化它时。 |
核心建议:
- 优先使用
dict.get(),这是处理字典键值访问最安全、最符合 Python 风格的方式。 - 使用
in关键字进行明确的条件判断,当你的逻辑比较复杂时。 - 避免直接使用
[],除非你通过其他方式(如in或try...except)确保了键的存在。
通过掌握这些方法,你就可以优雅地处理所有与字典键相关的操作,告别恼人的 KeyError。
