In addition to discussing readability, I think performance also matters in some scenarios. A quick timeit benchmark indicates that a test (i.e. “asking permission”) is actually slightly faster than handling the exception (i.e. “asking forgiveness”).
Here’s the code to set up the benchmark, generating a largeish dictionary of random key-value pairs:
setup = """
import random, string
d = {"".join(random.choices(string.ascii_letters, k=3)): "".join(random.choices(string.ascii_letters, k=3)) for _ in range(10000)}
"""
Then the if
test:
stmt1 = """
key = "".join(random.choices(string.ascii_letters, k=3))
if key in d:
_ = d[key]
"""
gives us:
>>> timeit.timeit(stmt=stmt1, setup=setup, number=1000000)
1.6444563979999884
whereas the approach utilizing the exception
stmt2 = """
key = "".join(random.choices(string.ascii_letters, k=3))
try:
_ = d[key]
except KeyError:
pass
"""
gives us:
>>> timeit.timeit(stmt=stmt2, setup=setup, number=1000000)
1.8868465850000575
Interestingly, hoisting the key
generation from the actual benchmark into the setup and therewith looking for the same key over and over, delivers vastly different numbers:
>>> timeit.timeit(stmt=stmt1, setup=setup, number=100000000)
2.3290171539999847
>>> timeit.timeit(stmt=stmt2, setup=setup, number=100000000)
26.412447488999987
I don’t want to speculate whether this emphasizes the benefits of a test vs. exception handling, or if the dictionary buffers the result of the previous lookup and thus biases the benchmark results towards testing… 🤔
if "blah" in B.keys()
, orif B.has_key("blah")
. – OrgandyA.update(B)
not work for you? – Schoolroomhas_key
has been deprecated in favor ofin
and checkingB.keys()
changes an O(1) operation into an O(n) one. – Acousticsupdate()
check for specific keys? – Auspex.has_key
is deprecated andkeys
creates unneeded list in py2k, and is redundant in py3k – SchoolroomB
it won't exist inA
according to OP's code, the same happens withupdate
– SchoolroomA = dict((k, v) for (k, v) in B if we_want_to_include(k))
. – Molalityif B.get("blah")
compare toif "blah" in B
? – Jacobahdict()
constructor, dict comprehension,collections.Counter
with+
operator, set.union()` or + operator,collections.defaultdict
, etc. – Coulter