tadhg.com
tadhg.com
 

Conditionally Adding dict Keys in Python

20:18 Tue 12 Oct 2010. Updated: 03:35 30 Dec 2010
[, ]

I frequently run across the need to add key/value pairs to a dict subject to some condition. The “traditional” version of that pattern looks something like this:

if condition:
    my_dict[key] = value

Because of my stylistic preferences, I don’t like that, and want to do this:

my_dict[key] = value if condition

That doesn’t work, though, because then key will be set to None in the dict, which is an unwanted side effect.

If the condition can be managed as part of a list comprehension, however, there’s a way around it.

The most common use case for me is where I have a dictionary containing more keys than I want, another dictionary that needs some but not all of the keys from the first, and a set of the keys I want to move from the second to the first. For example:

d1 = {"left": 1, "right": 2, "up": 3, "down": 4}
d2 = {"left": 5, "right": 6, "front": 7, "back": 8}

Let’s say I want the values for “left” and “right” from d2 to be inserted into d1, but I don’t want any values for “front” or “back” in d2. For a while I was using this:

for key in set("left", "right").intersection(d2.keys()):
    d1[key] = d2[key]

I like the functionality provided by intersection, but this feels somewhat unwieldy, and since sets aren’t as used as commonly as list comprehensions, I now think that this is better:

for key in [k for k in ["left", "right"] if k in d2]:
    d1[key] = d2[key]

That brings us back around, more or less, to the original problem. Now we can do this instead:

d1.update(dict([k, d2[k]] for k in ["left", "right"] if k in d2))

In other words, use dict() called on a list comprehension to create what we want to update the target dictionary with. This gets better in Python 2.7:

d1.update({k: d2[k] for k in ["left", "right"] if k in d2})

For comparison, the “traditional” approach to the same problem:

for k in ["left", "right"]:
    if k in d2:
        d1[k] = d2[k]

I know plenty of people who prefer that approach, but in my own code, that kind of thing stands out as a rough spot that needs to be smoothed; this is pretty clearly a matter of taste.

Leave a Reply