是否建议使用 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 异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查查询中是否有任何结果并添加if / else条件

如何在多个if / else条件下使用Throws?

如何在 if else 循环中对同一数据使用多个条件? - java/安卓

对于 IF Else 循环在单元格为空时不会停止

Python ❀ 条件判断语句

Python ❀ 条件判断语句