Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Understanding defaultdict

00:00 Welcome back. In the last lesson, we looked at how dictionaries handle missing keys using just what they have for being dictionaries. In this lesson, we’re ready to look a bit more closely at defaultdict.

00:12 The first thing you need to know about defaultdict is that it’s part of the standard library. Here is the documentation for the Python standard library.

00:20 If I scroll down,

00:22 you can see that here there’s an entry for collections under Data Types. And if I click on that and follow that link, then there’s an entry here for defaultdict. This is a dict subclass—remember, I told you that defaultdict inherits from dict—and what’s interesting about it is that it “calls a factory function to supply missing values.” And what they’re referring to, of course, is values which are missing for a certain key when you’re trying to access a key.

00:52 In case that was a bit too quick, I clicked on that link and came here to the documentation for defaultdict. What is interesting about defaultdict is that if a key isn’t present in the dictionary—or in the defaultdict, in this case—then that triggers .__missing__(). And .__missing__() in turn triggers .default_factory(), and this is what is going to generate a default value for the key which you were trying to access but wasn’t there.

01:18 This will become a bit more clear as we’re looking at examples in the REPL. In fact, let’s go there now. Here I am at the terminal, and I’m going to enter the Python REPL.

01:29 The first thing I’m going to do here is that from collections, I’m going to import defaultdict. There we go. So, this is what you would do anytime that you want to work with defaultdict: you would load it into memory from a package called collections. Before we move on, I would just like to prove to you that it is a subclass of dict, and I’ll do that using issubclass(). This takes two parameters.

01:52 The first is defaultdict—so, the object which I’m checking. And the second is the class which I want to know this object might be inheriting from—that would be dict.

02:04 And this returns True. So you can see I’m not lying. defaultdict does inherit from dict. And that means that, for the most part, it behaves just like a normal dictionary. Okay, so let’s create a defaultdict. We’re to name this one def_dict and I will use the assignment operator (=) and then the syntax is defaultdict()—and here, I have to pass a callable.

02:28 So this can be float, int, set, list, et cetera. I’m going to go with list for now. Now you’ll notice that I just used the keyword listthere’s no open and close of parentheses after list. In fact, that’s a common mistake, so do pay attention to that. Okay.

02:47 So now I have a defaultdict here. We can just check the type quickly and you can see this is a defaultdict and it comes from collections. And just like with a dictionary, I can assign values to keys. I’m going to create a first key, I’ll call it "one", and I’m going to sign the value 1so just the integer 1.

03:09 And you’ll see that if I call this the way I would with a dictionary, it returns the value 1. So that mapping works. Now let’s see what happens if I try to call a key which isn’t present.

03:22 So, "one" is there—we already know. Let’s try "missing".

03:27 You can see that unlike what happened in the introductory lesson, this didn’t error out. I didn’t get a traceback and I didn’t get a KeyError.

03:34 Instead, it smoothly returned a list, which is what I had set up here.

03:40 So, no error; my code continues to work. And I can use this list. In fact, let’s try something slightly different. Rather than trying to access "missing", which now isn’t missing, I will try accessing "another missing".

03:53 But remember, this is going to give me a list since there is no key for "another missing", so I can already treat this as a list—for example, by appending a value to it.

04:04 Now if I call my defaultdict just as I would a dict, I can see that it has three values in there, or three entries. The first is the key 'one', which is mapped to the int 1.

04:16 Then there’s the key 'missing', mapped to an empty list. And then finally, there is the key 'another missing', which contains a list, which in turn contains the integer 4.

04:29 These are the main takeaways from this lesson. Unlike what happens with a dictionary, which will give you a KeyError if you try to access a key which isn’t present, a defaultdict will trigger .__missing__(), which in turn triggers .default_factory().

04:43 The exact behavior of .default_factory() will depend on what you passed as a parameter when you first constructed your defaultdict. So in our example, I gave it list, and so it created a list whenever it encountered a key that was missing.

04:57 But as we’ll see later, you could also pass a set, an int, a float, et cetera. That all depends on the use case, and we’ll look at that in a minute.

05:06 I’ll see you in the next lesson, where we can practice using defaultdict.

Become a Member to join the conversation.