即便是经验最丰富的程序员也会犯错。对 Python 程序员来说,这些错误大致分为两类:错误(errors)和异常(exceptions)。 错误主要与语法有关,必须修复后程序才能运行。异常则发生在代码语法正确,但程序在运行时被某些情况中断。 在本教程中,我们将介绍新手和有经验的程序员都会遇到的一种常见异常:KeyError。我们将详解 Python 的 KeyError,并提供示例与多种处理该类异常的技术。若您想系统学习如何识别并修复 Python 中的错误,也可查看我们的Python 异常与错误处理 教程。
什么是 KeyError 异常?
在 Python 中,KeyError 是内置异常之一,用于处理多种常见错误情形。KeyError 可以理解为更通用的 LookupError 异常的子类之一(另一子类为 IndexError),它们都是 Exception 类的对象。 具体来说,当程序尝试访问字典中不存在的键时,就会引发 KeyError。字典是一种以键-值对存储数据的数据结构,字典中的值通过键来访问——这也正是 KeyError 名称的由来。
Python KeyError 的常见原因与示例
让我们看一个包含国家及其首都的字典示例:
dictionary_capitals = { 'Madrid' : 'Spain' ,
'Lisboa' : 'Portugal' , 'London' : 'United Kingdom' } 技术支持
要在字典中查询信息,需要在方括号内指定键,Python 会返回其关联的值。
dictionary_capitals[ 'Madrid' ] 技术支持
'Spain' 技术支持
如果尝试访问字典中不存在的键,Python 会给出 KeyError 异常的错误信息。
dictionary_capitals[ 'Rome' ] 技术支持
Traceback ( most recent call last) :
File "<stdin>" , line 1 , in < module>
KeyError: 'Rome' 技术支持
当我们尝试在其他采用字典形式的 Python 映射对象中访问不存在的键时,也会遇到 KeyError。例如,os.environ 对象返回一个字典,以键-值形式存储用户的环境变量。 在下面的代码中,我们尝试访问 os.environ 字典中键 USERS 对应的值。因为 USERS 不在 os.environ 中,代码触发了 KeyError。
os. environ[ 'USERS' ]
Traceback ( most recent call last) :
File "<stdin>" , line 1 , in < module>
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/os.py" , line 679 , in __getitem__
raise KeyError( key) from None
KeyError: 'USERS' 技术支持
事实是,字典在 Python 中非常常见 。另一个例子是更抽象的数据结构——哈希表(hashmap)。想进一步了解,请查看我们的Python 哈希表指南 教程。
处理 Python KeyError 异常
接下来探索处理 KeyError 的方法。我们有两种策略:要么预防 KeyError,要么通过异常处理捕获 KeyError。
预防 KeyError
如前所述,当我们访问不存在的键时,Python 会抛出 KeyError。为避免这种情况,可以使用字典的 .get() 方法,使代码更具容错性。使用该方法时,若键不存在,Python 会返回 None 而不是 KeyError。这是一个可取的做法。
print ( dictionary_capitals. get( 'Prague' ) ) 技术支持
None 技术支持
或者,我们也可以在访问前检查键是否存在。这种预防异常的方式被称为“先看一眼再说”(Look Before You Leap,简称 LBYL)。在这种情况下,可以使用 if 语句检查键是否存在;若不存在,则在 else 分支中进行处理。
capital = "Prague"
if capital in dictionary_capitals. keys( ) :
value = dictionary_capitals[ capital]
else :
print ( "The key {} is not present in the dictionary" . format ( capital) ) 技术支持
通过异常处理捕获 KeyError
第二种方法被称为“请求原谅比征得许可更容易”(Easier to Ask Forgiveness Than Permission,EAFP)。EAFP 实际上是 Python 中更常见的异常处理风格。
采用 EAFP 编码风格意味着我们默认假设键是有效存在的,如果假设不成立再捕获异常。LBYL 依赖 if/else 语句,而 EAFP 则依赖 try/except 子句。
在下面的示例中,我们不再检查键是否存在,而是直接尝试访问目标键。如果由于某种原因键不存在,就在 except 子句中捕获 KeyError 并妥善处理。
capital = "Prague"
try :
value = dictionary_capitals[ capital]
except KeyError:
print ( "The key {} is not present in the dictionary" . format ( capital) ) 技术支持
进阶的 Python KeyError 管理
使用 defaultdict 实现自动键处理
我们看到,只要尝试访问字典中不存在的键,Python 就会返回 KeyError。此前介绍的 .get() 方法是一种容错方式,虽然可用,但并非最优。Collections 模块提供了 defaultdict,这是一种更优的字典条目处理方式。与标准字典在访问缺失键时抛出 KeyError 不同,defaultdict 允许我们指定一个默认值,在找不到键时返回。下面的代码展示了如何从 Collections 导入 defaultdict,并用 lambda 函数创建默认值。若您对 lambda 函数感到困惑,可查看我们的Python lambda 教程 了解更多。
from collections import defaultdict
capitals = defaultdict( lambda : "The key doesn't exist" )
capitals[ 'Madrid' ] = 'Spain'
capitals[ 'Lisboa' ] = 'Portugal'
print ( capitals[ 'Madrid' ] )
print ( capitals[ 'Lisboa' ] )
print ( capitals[ 'Ankara' ] ) 技术支持
Spain
Portugal
The key doesn't exist技术支持
有意触发 KeyError
最后需要说明的是,在某些情况下,出于约束目的,有意抛出 KeyError 也是合适的做法。 我们知道,很多函数依赖特定数据来执行其操作。手动触发 KeyError 可以确保在缺失必要数据时,函数以清晰、可预期的方式失败。此时,随 KeyError 提供的错误信息能准确描述输入的问题,有助于调试。
下面用一个示例来说明。这里我们创建了一个以字典为参数的函数。为使函数正常工作,用户必须提供具有正确键的字典。之所以创建这样的函数,是因为我们希望在键缺失时立刻得知问题,而不是让错误在代码中继续传播。
def my_function ( my_dict) :
if 'critical_key' not in my_dict:
raise KeyError( 'critical_key is missing from the dictionary. Please modify the dictionary' ) 技术支持
结语
希望本文对您有所帮助。KeyError 是 Python 开发者最常遇到的异常之一。掌握错误与异常处理的技巧,是成为优秀 Python 程序员的关键一步。想了解更多函数式编程技术与编码基础,请查看我们的 Python 编程 与 Python 基础 技能路径。另外,您也可以阅读我们的Python 集合与集合论 教程,拓展相关概念。
即便是经验最丰富的程序员也会犯错。对 Python 程序员来说,这些错误大致分为两类:错误(errors)和异常(exceptions)。
错误主要与语法有关,必须修复后程序才能运行。异常则发生在代码语法正确,但程序在运行时被某些情况中断。
在本教程中,我们将介绍新手和有经验的程序员都会遇到的一种常见异常:
KeyError。我们将详解 Python 的KeyError,并提供示例与多种处理该类异常的技术。若您想系统学习如何识别并修复 Python 中的错误,也可查看我们的Python 异常与错误处理教程。什么是 KeyError 异常?
在 Python 中,
KeyError是内置异常之一,用于处理多种常见错误情形。KeyError可以理解为更通用的LookupError异常的子类之一(另一子类为IndexError),它们都是Exception类的对象。具体来说,当程序尝试访问字典中不存在的键时,就会引发
KeyError。字典是一种以键-值对存储数据的数据结构,字典中的值通过键来访问——这也正是KeyError名称的由来。Python KeyError 的常见原因与示例
让我们看一个包含国家及其首都的字典示例:
要在字典中查询信息,需要在方括号内指定键,Python 会返回其关联的值。
如果尝试访问字典中不存在的键,Python 会给出
KeyError异常的错误信息。当我们尝试在其他采用字典形式的 Python 映射对象中访问不存在的键时,也会遇到
KeyError。例如,os.environ对象返回一个字典,以键-值形式存储用户的环境变量。在下面的代码中,我们尝试访问
os.environ字典中键USERS对应的值。因为USERS不在os.environ中,代码触发了KeyError。事实是,字典在 Python 中非常常见。另一个例子是更抽象的数据结构——哈希表(hashmap)。想进一步了解,请查看我们的Python 哈希表指南教程。
处理 Python KeyError 异常
接下来探索处理
KeyError的方法。我们有两种策略:要么预防KeyError,要么通过异常处理捕获KeyError。预防 KeyError
如前所述,当我们访问不存在的键时,Python 会抛出
KeyError。为避免这种情况,可以使用字典的.get()方法,使代码更具容错性。使用该方法时,若键不存在,Python 会返回None而不是KeyError。这是一个可取的做法。或者,我们也可以在访问前检查键是否存在。这种预防异常的方式被称为“先看一眼再说”(Look Before You Leap,简称 LBYL)。在这种情况下,可以使用
if语句检查键是否存在;若不存在,则在else分支中进行处理。通过异常处理捕获 KeyError
第二种方法被称为“请求原谅比征得许可更容易”(Easier to Ask Forgiveness Than Permission,EAFP)。EAFP 实际上是 Python 中更常见的异常处理风格。
采用 EAFP 编码风格意味着我们默认假设键是有效存在的,如果假设不成立再捕获异常。LBYL 依赖 if/else 语句,而 EAFP 则依赖 try/except 子句。
在下面的示例中,我们不再检查键是否存在,而是直接尝试访问目标键。如果由于某种原因键不存在,就在 except 子句中捕获
KeyError并妥善处理。进阶的 Python KeyError 管理
使用 defaultdict 实现自动键处理
我们看到,只要尝试访问字典中不存在的键,Python 就会返回
KeyError。此前介绍的.get()方法是一种容错方式,虽然可用,但并非最优。Collections模块提供了defaultdict,这是一种更优的字典条目处理方式。与标准字典在访问缺失键时抛出KeyError不同,defaultdict允许我们指定一个默认值,在找不到键时返回。下面的代码展示了如何从Collections导入defaultdict,并用lambda函数创建默认值。若您对 lambda 函数感到困惑,可查看我们的Python lambda 教程了解更多。有意触发 KeyError
最后需要说明的是,在某些情况下,出于约束目的,有意抛出
KeyError也是合适的做法。我们知道,很多函数依赖特定数据来执行其操作。手动触发
KeyError可以确保在缺失必要数据时,函数以清晰、可预期的方式失败。此时,随KeyError提供的错误信息能准确描述输入的问题,有助于调试。下面用一个示例来说明。这里我们创建了一个以字典为参数的函数。为使函数正常工作,用户必须提供具有正确键的字典。之所以创建这样的函数,是因为我们希望在键缺失时立刻得知问题,而不是让错误在代码中继续传播。
结语
希望本文对您有所帮助。
KeyError是 Python 开发者最常遇到的异常之一。掌握错误与异常处理的技巧,是成为优秀 Python 程序员的关键一步。想了解更多函数式编程技术与编码基础,请查看我们的 Python 编程 与 Python 基础技能路径。另外,您也可以阅读我们的Python 集合与集合论教程,拓展相关概念。