Suppose I want to create a dict
(or dict
-like object) that returns a default value if I attempt to access a key that's not in the dict
.
I can do this either by using a defaultdict
:
from collections import defaultdict
foo = defaultdict(lambda: "bar")
print(foo["hello"]) # "bar"
or by using a regular dict
and always using dict.get(key, default)
to retrieve values:
foo = dict()
print(foo.get("hello", "bar")) # "bar"
print(foo["hello"]) # KeyError (as expected)
Other than the obvious ergonomic overhead of having to remember to use .get()
with a default value instead of the expected bracket syntax, what's the difference between these 2 approaches?
Asides from the ergonomics of having .get
everwhere, one important difference is if you lookup a missing key in defaultdict
it will insert a new element into itself rather than just returning the default. The most important implications of this are:
defaultdict
defaultdict
, with .get
the default is lost unless stored explictyfrom collections import defaultdict
default_foo = defaultdict(list)
dict_foo = dict()
for i in range(1024):
default_foo[i]
dict_foo.get(i, [])
print(len(default_foo.items())) # 1024
print(len(dict_foo.items())) # 0
# Defaults in defaultdict's can be mutated where as with .get mutations are lost
default_foo[1025].append("123")
dict_foo.get(1025, []).append("123")
print(default_foo[1025]) # ["123"]
print(dict_foo.get(1025, [])) # []