kevin
kevin

Reputation: 147

Using append method in a for loop

I'm currently looking at this code snippet from Think Python implementing an inverted dictionary with the setdefault method, and I'm unclear on why it works:

def invert_dict(d):
"""Inverts a dictionary, returning a map from val to a list of keys.

If the mapping key->val appears in d, then in the new dictionary
val maps to a list that includes key.

d: dict

Returns: dict
"""
    inverse = {}
    for key, val in d.iteritems():
        inverse.setdefault(val, []).append(key)
    return inverse

Reading from left to right in the for loop, inverse.setdefault(val, []) creates an entry in the dictionary, not a list. So how can we use the append method?

Upvotes: 2

Views: 185

Answers (1)

Patrick Maupin
Patrick Maupin

Reputation: 8137

You can use the append method, because setdefault itself returns the value of dict[val] after initializing it if necessary. So the first time setdefault is called on a particular dictionary key, it sets inverse[val] to the second parameter (the empty list) and then returns that empty list. That is the list you are appending to.

This particular paradigm is out of date for this particular use-case, btw. The best way to do it now is:

import collections
inverse = collections.defaultdict(list)
for key, val in d.items():
    inverse[val].append(key)

The reason is that setdefault creates a new empty list object every time through the list, and then immediately discards the newly created object if inverse[val] already exists.

Also, iteritems() is still more efficient for Python 2, but it doesn't exist in Python 3 and items() in Python 3 works the same as iteritems() in Python 2.

Upvotes: 1

Related Questions