猿问

为什么“try ... except KeyError ...”比“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也应该做类似的判断键是否存在于dict中的逻辑。


绝地无双
浏览 139回答 1
1回答

MM们

当例外情况是不常见情况时,您所学的规则适用。如果您通常要查找该值,那么d['a']包装在很少调用异常处理机制的try/except KeyError:中将会获胜;如果您通常不会找到该值,则抛出和捕获异常的开销将超过使用泛型方法 dispatch ( d.get('a')) 与更直接的语法支持方法 ( ) 相比更高的相对开销d['a']。在现代 (3.7+) CPython 中尤其如此,其中方法调用得到了一些额外的优化,减少了d.get('a').正如您在评论中指出的那样,在查找成功的情况下,get速度保持相同,而未d['a']使用的except KeyError:速度明显更快。在许多情况下它也更正确;如果dict有映射到 的键None,您get的基于 的代码将不会区分“键未找到”和“键映射到None”,这可能是您想要的,但通常不是。
随时随地看视频慕课网APP

相关分类

Python
我要回答