简体   繁体   中英

Why is "try ... except KeyError ..." slower than "dict.get"?

Long time before, someone told me

d = {}
try:
    a = d['a']
    # do something
except KeyError:
    # do something else

is faster than

a = d.get('a')
if a:
    # do something
else:
    # do something else

But today, after I did a simple test, I found the result just on the contrary:

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

So why does it happened? In my imagine, d.get should also do the similar logic that judge whether the key is existing in the dict.

The rule you were taught applies when the exceptional case is the uncommon case. If you're usually going to find the value, d['a'] wrapped in a try / except KeyError: that rarely invokes the exception handling machinery will win; if you're usually not going to find the value, the overhead of throwing and catching the exception will outweigh the higher relative overhead of using generic method dispatch ( d.get('a') ) vs. the more direct syntax-supported approach ( d['a'] ). That's especially true in modern (3.7+) CPython, where method calls got some additional optimization , reducing the overhead of d.get('a') .

As you note in the comments , in cases where the lookup succeeds , get remains the same speed, while d['a'] with an unused except KeyError: speeds up to be significantly faster. It's also more correct in many cases; if the dict had keys that mapped to None , your get -based code would wouldn't distinguish "key not found" from "key maps to None ", which might be what you want, but often isn't.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM