jump to navigation

Some Dict Patterns August 10, 2011

Posted by PythonGuy in Advanced Python, Python.
trackback

Introduction

I have seen a lot of Python code, as well as Java, Perl, and other languages. When dealing with dicts, I have identified a few patterns that I feel are optimal, depending on the situation. These are extraordinarily simple.

NOTE: The dict data structure is known by many names: map, a hashmap, an associative array, a hash, or even a table.

Use if Present

For instance, how many times have you written the following pseudo-code in your language of choice?

# pseudo-code
if key is in map:
    lookup value in map with key
    use value

Python provides the “get()” method which returns None if it is not present.

# Python
value = map.get(key)
if value is not None:
    # use value

Of course, sometimes you need to distinguish between values that are None and that are not present in the dict. You can rely on exceptional behavior for this:

# Python
try:
    value = map[key]
except KeyError:
    pass
else:
    # use value

Or you can use the “in” test:

# Python
if key in map:
    value = map[key]
    # use value

The above, of course, does 2 dict lookups.

Exceptions versus Lookups

There is discussion about whether to use exceptions or lookups. The general rule of thumb is that exceptions are not as slow as you think, since Python is pretty slow to begin with. “Slow”, of course, is a relative term that is meaningful when you compare Python to C/C++. And nowadays with PyPy, “slow” isn’t a proper word for it anymore.

Use Value or Default If Missing

Sometimes you want to use a default value if the key is not present. This is simply:

# Python
value = map.get(key, 'default')

Note that whatever expression you use as the default value will be evaluated, whether or not it was used. If the expression is expensive to calculate, then you can use this form:

# Python
value = map.get(key)
if value is None:
    value = expensive_expression()

Notice that you’re back to the previous pattern if you need to distinguish between a value of None and a missing key.

Use Value or Default and Store if Missing

Sometimes you want to store the default value in the dict if it is missing. “setdefault()” is the ideal method for this.

# Python
value = map.setdefault(key, 'default')

Of course, the caveats for expensive default expressions applies.

Conclusion and Summary

Those of you who are unfamiliar with Python might note how similar all of the above patterns are. Indeed, if you simply learn what the following expressions mean, you don’t have to think very hard to understand what the code does or to choose the right code:

  • key in dict
  • dict[key]
  • dict.get(key)
  • dict.get(key, default)
  • dict.setdefault(key, default)

Comments»

1. Daniel Widyono - August 15, 2011

Nice thorough treatment; I was just looking into this today and found lots of snippets around the Net, but yours collects quite a bit together at once.

Would you care to add commentary on collections.defaultdict? I realize it’s not a pure dict, but it’s That is what I ended up using in my code, where I’m explicitly updating a dict with “blah['key'] += value”. This is in place of “blah['key'] = blah.get(‘key’, 0) + value”. I just like how the former cleanly reads like my thought process.

Daniel Widyono - August 15, 2011

Oops… “not a pure dict, but it’s in the standard library.”

2. PythonGuy - August 15, 2011

defaultdict is good only when you want the default values for all the keys to be the same. I haven’t found a common use for this, except perhaps configuration dicts.

Daniel Widyono - August 16, 2011

Agreed. The one limited use in my case is a slew of counters, indexed by name. Counters will all begin at zero and are all ints. I suppose you could call those measurement dicts?

For me, the primary gain is syntactic; I can do += as above, or with lists, I can append without having to initialize an empty list for the one-time case of a non-existent key.

Cheers

PythonGuy - August 16, 2011

That’s a good case.

3. AdriƠ Cereto-MassaguƩ - December 18, 2011

I prefer to use an if with dict.has_key(key), which I find more readable.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.