What does the below sentence mean in the context of defaultdict
? I know how defaultdict
works, but I have no idea what is meant by this sentence. Can anyone explain?
One caution with
defaultdict
is that it will automatically create dictionary entries for defaultdict keys accessed later on (even if they aren’t currently found in the dictionary).
-- From a Python book I'm reading.
from collections import defaultdict
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)
One caution with defaultdict
is that it will automatically create dictionary entries for defaultdict
keys accessed later on (even if they aren’t currently found in the dictionary). If you don’t
want this behavior, you might use setdefault
on an ordinary dictionary instead. For example:
d = {} # A regular dictionary
d.setdefault('a', []).append(1)
d.setdefault('a', []).append(2)
d.setdefault('b', []).append(4)
CodePudding user response:
In other words:
defaultdict
is useful because it provides a default when the key does not exist. However, this is also a danger because a programming error may go uncaught because of this -- For example, a typo in a key name would otherwise produce a KeyError
but will not with a defaultdict
.
# example with dict
mydict = {}
mydict['a'] = list()
mydict['a'].append('foo')
# example with defaultdict
mydefaultdict = defaultdict(list)
mydefultdict['a'].append('foo')
# Now, imagine a typo occurs accessing each example:
# the key 'aa' is mistakenly used instead of 'a'
print(mydefaultdict['aa']) # no error
print(mydict['aa']) # KeyError is raised
So, in this way, defaultdict can produce a hazard where errors like this do not cause the program to stop and can make it difficult to debug because the erroneous access may only produce an error after the unexpected value is passed far later in the program.
The book offers a strange solution to this -- using setdefault
. While this works, it kind of defeats part of the purpose in why you would use defaultdict to begin with.
The problem described by the book can be avoided in a much simpler way -- by setting mydefaultdict.default_factory = None
when you no longer want the default dict to produce defaults.
mydefaultdict = defaultdict(dict)
foo['bar']['baz'] = 'bacon'
foo['eggs']['spam'] = 'foo'
mydefaultdict.default_factory = None
# now it behaves like a normal dictionary
foo['eggz'] # KeyError
CodePudding user response:
As the caution states, accessing an element outside the context of trying to set a value in a defaultdict
will create an entry:
In [2]: d = defaultdict(list)
In [3]: d['c']
Out[3]: []
In [4]: d
Out[4]: defaultdict(list, {'c': []})
On a regular dictionary without the setdefault
, the access attempt would throw a KeyError
.