Credit: Alex Martelli
Working with a dictionary
D
, you need to use the entry
D[k]
if it’s already present, or
add a new D[k]
if k
isn’t yet a key in D
.
This is what the
setdefault
method of dictionary objects is for. Say we’re
building a word-to-page numbers index. A key piece of code might be:
theIndex = {} def addword(word, pagenumber): if theIndex.has_key(word): theIndex[word].append(pagenumber) else: theIndex[word] = [pagenumber]
Good Pythonic instincts suggest substituting this “look before you leap” pattern with an “easier to get permission” pattern (see Recipe 5.4 for a detailed discussion of these phrases):
def addword(word, pagenumber): try: theIndex[word].append(pagenumber) except KeyError: theIndex[word] = [pagenumber]
This is just a minor simplification, but it satisfies the pattern of
“use the entry if it is already present; otherwise,
add a new entry.” Here’s how using
setdefault
simplifies this further:
def addword(word, pagenumber): theIndex.setdefault(word, []).append(pagenumber)
The setdefault
method of a dictionary is a handy
shortcut for this task that is especially useful when the new entry
you want to add is mutable. Basically, dict.setdefault(k, v)
is much like dict.get(k, v)
, except
that if k
is not a key in the dictionary, the
setdefault
method assigns
dict[k]=v
as a side effect, in addition to
returning v
. (get
would just
return v
, without affecting
dict
in any way.) Therefore,
setdefault
is appropriate any time you have
get
-like needs but also want to produce this
specific side effect on the dictionary.
setdefault
is particularly useful in a dictionary
with values that are lists, as detailed in Recipe 1.6. The single most typical usage form for
setdefault
is:
somedict.setdefault(somekey, []).append(somevalue)
Note that setdefault
is normally not very useful
if the values are immutable. If you just want to count words, for
example, something like the following is no use:
theIndex.setdefault(word, 1)
In this case, you want:
theIndex[word] = 1 + theIndex.get(word, 0)
since you will be rebinding the dictionary entry at
theIndex[word]
anyway (because numbers are
immutable).
Recipe 5.4; the Library Reference section on mapping types.
Get Python Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.