是否建议使用 if...else 条件来检查键或使用 try...except 在 python 中捕获 KeyError 异常?
Posted
技术标签:
【中文标题】是否建议使用 if...else 条件来检查键或使用 try...except 在 python 中捕获 KeyError 异常?【英文标题】:Is it recommended to use if...else condition to check for keys or use try...except to catch KeyError exceptions in python? 【发布时间】:2020-01-13 06:03:26 【问题描述】:所以,假设有一个字典 var_dict
,我想打印一个键 a
的值,例如。
所以,一种方法是:
if var_dict is None:
return
if 'a' not in var_dict.keys():
return
print(var_dict['a'])
其他方法是:
try:
print(var_dict['a'])
except (KeyError, TypeError):
return
我的问题是推荐哪个。我在这里读到:Python: try-except vs if-else to check dict keys,异常处理速度较慢,但如果我们指定预期的错误怎么办?在这种情况下也很慢吗?
【问题讨论】:
您可以使用var_dict.get('a')
,它将返回None
,而不是出错。另外,你不需要var_dict.keys()
,只需'a' not in var_dict
就足够了
.get
工作时不会抛出异常
添加到@sshashank124的评论,你只需要检查if var_dict is None:
,然后你直接转到dict.get
。
【参考方案1】:
try/except 块确实比较慢。我会这样做:
def foobar(var_dict):
return var_dict['a'] if var_dict and 'a' in var_dict else None
例如:
In [1]: def foobar(var_dict):
...: return var_dict['a'] if var_dict and 'a' in var_dict else None
...:
In [2]:
In [2]: foobar(None)
In [3]: foobar('x': 1)
In [4]: foobar('a': 1)
Out[4]: 1
或者,如果您知道 var_dict 是一个字典(而不是 None),get()
有一个默认值:
return var_dict.get('a', None)
【讨论】:
【参考方案2】:try/except
块来检索密钥或默认值将比所有其他替代方法快得多。例如
from time import time
t = time()
for i in range(1000000):
v = __builtins__['int'] if 'int' in __builtins__ else None
print(time() - t)
t = time()
for i in range(1000000):
v = __builtins__.get('int', None)
print(time() - t)
t = time()
for i in range(1000000):
try:
v = __builtins__['int']
except KeyError:
v = None
print(time() - t)
结果:
0.12224698066711426
0.15873217582702637
0.0927286148071289
第一个要慢得多,因为 Python 基本上检索密钥两次。通过__contains__
,然后通过__getitem__
。第二个比较慢,因为 Python 会进行一些内部验证,而 try/catch
直奔主题或失败。
请求宽恕比请求许可更容易。
【讨论】:
【参考方案3】:使用第二种方法。来自Python Glossary:
EAFP: 请求宽恕比请求许可更容易。这种常见的 Python 编码风格假设存在有效的键或属性,如果假设被证明是错误的,则捕获异常。这种干净快速的风格的特点是存在许多 try 和 except 语句。该技术与许多其他语言(如 C)常见的 LBYL 风格形成鲜明对比。
为了确定,我刚刚在 jupyter 中尝试了使用 %%timeit 魔术命令,第二个选项稍微快一些。
【讨论】:
以上是关于是否建议使用 if...else 条件来检查键或使用 try...except 在 python 中捕获 KeyError 异常?的主要内容,如果未能解决你的问题,请参考以下文章