Concepts / Building Histograms with Dictionaries

Building Histograms with Dictionaries

The get() method safely retrieves dictionary values, returning a default if the key is missing.

  • Programming

From Items to Counts

A histogram built with a dictionary records how often items occur. Each observed item becomes a dictionary key, and its value records the number of times that item has appeared. The main difficulty is the first occurrence: before an item has been counted, its key may not exist in the dictionary. Python's get() method handles that missing-key case by returning a default value.

What do you think happens?

Suppose counts is an empty dictionary and item is the first value being counted. What starting count should get() provide?

  • The current count stored for item
  • 0
  • 1
  • An arbitrary value
Reveal answer

Answer: 0

When the key is missing, get() returns the default supplied as its second argument. Starting from 0 makes it possible to add 1 for the item's first occurrence.

How get() Chooses a Value

The get() method looks up a key in a dictionary. If the key exists, get() retrieves the value associated with that key. If the key is missing, get() returns the default value supplied to it. This makes get() useful when a program cannot assume that every key has already been added.

python
Output
2
0

The first lookup finds the existing key red, so the stored value 2 is returned. The second lookup cannot find blue, so the default 0 is returned. The default does not represent a newly stored key by itself; it is the value produced by the lookup when the key is absent.

yesnoLook up keycounts.get(key, 0)Key exists?Stored valueexisting key0missing key default
What happens when get() looks up a key that exists versus a key that is missing?

The Counting Idiom

The standard counting expression is d[c] = d.get(c, 0) + 1. It reads the current count for key c, uses 0 when c is not present, adds 1 for the newly observed item, and stores the resulting count back under c.

counts[item] = counts.get(item, 0) + 1

Counting Three Items

Start with an empty dictionary and process the items red, blue, and red.

Process red: red is missing, so get() returns 0. Adding 1 produces 1, which is stored for red.

Process blue: blue is missing, so get() returns 0. Adding 1 produces 1, which is stored for blue.

Process red again: red already has the count 1. Adding 1 produces 2, which replaces the previous count for red.

{"red": 2, "blue": 1}

count itemcount itemcount itemEmpty counts{}red{"red": 1}blue{"red": 1, "blue": 1}red{"red": 2, "blue": 1}
How does each input item move through the loop and update its corresponding key-value count?

Refactoring the Loop

Before get() is used, a counting loop commonly needs explicit logic for the two cases: the key is already present, or the key is missing. The get() idiom puts both cases into one assignment. The result is more concise and is described in the source material as more Pythonic and less error-prone when keys may not exist.

The two versions express the same counting idea. In the longer version, the missing-key case assigns 1 directly. In the shorter version, the missing-key case starts at 0 and then adds 1. For an existing key, both versions increase the previous count by 1.

refactorif item in countsbranch for existing ormissing keycounts.get(item, 0) +1one counting expression
How does control flow change when the explicit missing-key check is replaced with counts.get(item, 0) + 1?

Mistakes with Missing Keys

  • Using bracket notation as though every key already exists

    The counting expression assumes that item already has a stored count, but the first occurrence may arrive before that key has been added.

    Fix: Use counts[item] = counts.get(item, 0) + 1 so a missing key starts from the default count 0.

  • Forgetting to add 1 after retrieving the count

    The lookup retrieves the old count or the default, but it does not increase the total for the current occurrence.

    Fix: Add 1 before storing the result: counts[item] = counts.get(item, 0) + 1.

  • Using a default other than 0 for a new count

    A new item would begin at 1 and then be increased again, so its first occurrence would be counted as 2.

    Fix: Use 0 as the default starting count, then add 1 for the current item.

Practice the Pattern

EASY

Write a loop that builds a histogram for the items in the list ["cat", "dog", "cat", "bird", "dog", "cat"]. Use get() rather than an if-statement. What dictionary should the loop produce?

Hints
  • Begin with an empty dictionary named counts.
  • For each item, assign counts[item] the result of counts.get(item, 0) + 1.
  • The item cat occurs three times, dog occurs two times, and bird occurs one time.
python
Output
{"cat": 3, "dog": 2, "bird": 1}

Key Takeaways

  1. get() returns the stored value when a dictionary key exists.
  2. When the key is missing, get() returns the supplied default value.
  3. The counting idiom d[c] = d.get(c, 0) + 1 handles first and later occurrences in one line.
  4. A dictionary histogram maps each observed item to its occurrence count.
  5. Using get() avoids a separate missing-key branch and is more Pythonic and less error-prone for this counting pattern.

Key Takeaways

  • get() retrieves an existing dictionary value or returns a chosen default for a missing key.
  • The default 0 represents the number of earlier occurrences before the current item is counted.
  • The expression d[c] = d.get(c, 0) + 1 replaces a longer if-statement counting pattern.
  • Repeatedly applying this expression builds a histogram of item frequencies.