[英]Why is "try ... except KeyError ..." slower than "dict.get"?
很久以前,有人告诉我
d = {}
try:
a = d['a']
# do something
except KeyError:
# do something else
比
a = d.get('a')
if a:
# do something
else:
# do something else
但是今天,我做了一个简单的测试后,发现结果恰恰相反:
import time
d = {}
n = 0
t1 = time.time()
for i in range(1000000):
try:
a = d['a']
except KeyError:
n += 1
print(time.time() - t1)
>>> 0.4676947593688965
import time
d = {}
n = 0
t1 = time.time()
for i in range(1000000):
a = d.get('a')
if a is None:
n += 1
print(time.time() - t1)
>>> 0.3045947551727295
那为什么会这样呢? 在我的想象中, d.get
也应该做类似的逻辑判断键是否存在于字典中。
当例外情况是不常见情况时,您所学的规则适用。 如果您通常要查找该值,则d['a']
包装在try
/ except KeyError:
中,很少调用异常处理机制将获胜; 如果您通常不会找到该值,则抛出和捕获异常的开销将超过使用泛型方法分派 ( d.get('a')
) 与更直接的语法支持方法的相对开销( d['a']
)。 在现代 (3.7+) CPython 中尤其如此,方法调用得到了一些额外的优化,减少了d.get('a')
的开销。
正如您在评论中指出的那样,在查找成功的情况下, get
保持相同的速度,而d['a']
具有未使用的except KeyError:
速度明显更快。 在许多情况下它也更正确; 如果dict
具有映射到None
的键,则基于get
的代码将不会区分“找不到键”和“键映射到None
”,这可能是您想要的,但通常不是。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.