Home > Enterprise >  defaultdict automatically creating dictionary entries for keys accessed later on
defaultdict automatically creating dictionary entries for keys accessed later on

Time:12-19

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.

  • Related