DEV Community

loading...
Cover image for TIGEW: defaultdict

TIGEW: defaultdict

saramccombs profile image Sara McCombs (she/her) ・3 min read

Photo by Kelly Sikkema on Unsplash

In a recent PR review, using defaultdict instead of a regular dictionary was suggested. Having never worked with defaultdict I needed to take a moment to understand the suggested refactor.

Keeping with the theme, here's another installment of Things I Google Each Week focusing on defaultdict.

What is defaultdict?

The Python defaultdict behaves almost exactly like a regular Python dictionary, however, if you try to access or modify a missing key defaultdict will automatically create the key and generate a default value.

Remember: A Python dictionary holds key:value pairs, the key must be unique and immutable.

Defaultdict is a sub-class of the dict class that returns a dictionary-like object and never raises a KeyError due to the default value.

This makes defaultdict a valuable option for handling missing keys in dictionaries.

When/How to Use defaultdict?

Lets compare a dictionary and a defaultdict:

# Python dictionary 

st_dict = {1: 'Picard', 2: 'Spock', 3: 'Tasha Yar', 4: 'Data'}  
print("Star Trek Characters:")  
print(st_dict) 
print(st_dict[1]) 
print(st_dict[5])

# print(st_dict[5]) will raise a KeyError as
# the 5 key is not present in the dictionary 
Enter fullscreen mode Exit fullscreen mode

Output:

Star Trek Characters:
{1: 'Picard', 2: 'Spock', 3: 'Tasha Yar', 4: 'Data'}
Picard
Traceback (most recent call last): File "/home/dictionary_example.py",
line 7, in print(st_dict[5])
KeyError: 5
Enter fullscreen mode Exit fullscreen mode

Now here's a defualtdict:

# Python defaultdict 

from collections import defaultdict 

# Function to return a default value for keys that are missing 
def def_value(): 
    return "Captains Log..."

# Defining the defaultdict 
st_dict = defaultdict(def_value) 
st_dict["Picard"] = "Captain"
st_dict["Spock"] = "Commander"
st_dict["Tasha Yar"] = "Lieutenant"
st_dict["Data"] = "Lieutenant Commander"

print(st_dict["Picard"]) 
print(st_dict["Spock"]) 
print(st_dict["Geordi"]) 
Enter fullscreen mode Exit fullscreen mode

Output:

Captain
Commander
Captains Log...
Enter fullscreen mode Exit fullscreen mode

See the difference? Which one might be easier to handle in your project?

What are some other interesting features of defaultdict?

Default_factory

The function provided in the defaultdict definition is known as the default_factory.

As a general FYI, if this argument is absent from the defaultdict it raises a KeyError when a missing key is encountered. Just like a dictionary.

# Python defaultdict - default_factory

from collections import defaultdict

# Defining the defaultdict
# using lambda this time
st_dict = defaultdict(lambda: "Captain's Log...")
st_dict["Picard"] = "Captain"
st_dict["Spock"] = "Commander"
st_dict["Tasha Yar"] = "Lieutenant"
st_dict["Data"] = "Lieutenant Commander"

print(st_dict["Picard"]) 
print(st_dict["Spock"]) 
print(st_dict["Geordi"]) 
Enter fullscreen mode Exit fullscreen mode

Output:

Captain
Commander
Captains Log...
Enter fullscreen mode Exit fullscreen mode

missing()

A method to return the default value of a given defaultdict.

# Python defaultdict - __missing__()

from collections import defaultdict

# Defining the defaultdict
st_dict = defaultdict(lambda: "Captain's Log...")
st_dict["Picard"] = "Captain"
st_dict["Spock"] = "Commander"
st_dict["Tasha Yar"] = "Lieutenant"
st_dict["Data"] = "Lieutenant Commander"

print(st_dict.__missing__("Geordi"))
print(st_dict.__missing__("Worf"))
print(st_dict.__missing__("Picard"))
Enter fullscreen mode Exit fullscreen mode

Output:

Captain's Log...
Captain's Log...
Captain's Log...
Enter fullscreen mode Exit fullscreen mode

Using list as default_factory

When the list method is passed as the default_factory argument, then a defaultdict is created that will default new values to an empty list.

# Python defaultdict - default_factory with list

from collections import defaultdict

# Defining the defaultdict
number_dict = defaultdict(list)

for i in range(5):
   number_dict[i].append(i)

print("Dictionary with list value:")
print(number_dict)
Enter fullscreen mode Exit fullscreen mode

Output:

Dictionary with list value:
defaultdict(<class 'list'>, {0: [0], 1: [1], 2: [2], 3: [3], 4: [4]})
Enter fullscreen mode Exit fullscreen mode

Using int as default_factory

When the int method is passed as the default_factory argument, then a defaultdict is created with default value as zero.

# Python defaultdict - default_factory with int

from collections import defaultdict

# Defining the defaultdict
numbers_dict = defaultdict(int)

numbers = [10, 20, 30 ]

# Iterate through the list
for i in numbers:
    numbers_dict[i] = i*2

print(numbers_dict)
print(numbers_dict[40])
Enter fullscreen mode Exit fullscreen mode

Output:

defaultdict(<class 'int'>, {10: 20, 20: 40, 30: 60})
0
Enter fullscreen mode Exit fullscreen mode

Where Can I Learn More?

  1. Real Python - Using the Python defaultdict Type for Handling Missing Keys
  2. Geeks for Geeks - Defaultdict in Python
  3. Accelebrate - Using defaultdict in Python

Discussion (0)

pic
Editor guide