OrderedDict and defaultdict
00:00
In the previous lesson, I concentrated on the dict
type, which is built into Python. In this lesson, I’m going to cover OrderedDict
and defaultdict
, which are part of the collections
standard library.
00:13
The built-in dict
type isn’t the only kind of dictionary that Python provides. There are others in the standard library. OrderedDict
, part of the collections
library, remembers the insertion order of the keys.
00:26
It also provides some other useful functionality as well. It supports iteration over the dictionary using Python’s built-in reversed()
method, and then provides two additional methods that the standard dictionary doesn’t have. .move_to_end()
moves a key inside of OrderedDict
to the end of the listing, as if it was the last thing inserted.
00:48
And .popitem()
—although that’s supported by the standard dictionary type, the OrderedDict
type takes an additional parameter, allowing you to pop either the first item or the last item off the OrderedDict
.
01:01
Depending on how closely you’ve been following along with the changes to the dictionary in CPython implementations, OrderedDict
might be a bit of a surprise that it exists. And that’s because as of Python 3.6, dict
type itself maintained order.
01:16
It did that as part of how it was implemented but wasn’t part of the language specification. Python 3.7 changed the specification so that maintaining the order was a requirement of the dict
type.
01:29
Support for working with the built-in reversed()
function was added to dict
in Python 3.8, so if you’re using Python 3.8 or 3.9, the built-in dict
type is very, very similar to OrderedDict
.
01:42
They haven’t removed OrderedDict
in order to maintain backward compatibility, but for the most part, you no longer need to use it explicitly.
01:50
Although almost everything that I’m about to show you is possible with the built-in dict
type in Python 3.9—the version of the language I’m using—I’m going to explicitly use OrderedDict
from collections
in case you’re using an older version and need to follow along.
02:07 Once you have it imported, you can create it by instantiating the class.
02:14
The constructor for the OrderedDict
class takes an arbitrary number of arguments. It automatically creates a dictionary mapping the keys to the values of those arguments passed in. And there’s the repr for it.
02:29
Notice that it displays it like a list, showing that 1
, 2
, and 3
were inserted, in that order. Like a regular dictionary, you can use the square bracket notation to insert items into the dictionary.
02:43
And 4
has been appended to the end.
02:48 And notice, although I’ve been putting numbers in here for clarity’s sake, that has nothing to do with the order in the dictionary. It’s not sorting—it’s based on the insertion order.
03:00
Similar to the built-in dict
type, OrderedDict
supports the .keys()
method. And the reversed()
function is also supported on the dictionary. This returns an iterator, which, if I turn into a list, shows you the value of the keys in reverse of insertion order.
03:20
One of the differences between the OrderedDict
and the built-in type is the support for the .move_to_end()
method.
03:30 This tells the class to take the indicated key and move it to the end of the ordering in the list, thus restoring my numeric order of my dictionary.
03:43
Just like a regular dictionary, OrderedDict
supports the .popitem()
method. This pulls the last item off and returns it. The dictionary now does not contain the key 'four'
.
03:53
Unlike the regular dictionary type, OrderedDict
also supports a parameter to .popitem()
. If you pass in False
, it will pop the first item off the list instead of the last one.
04:06
And there I’ve pulled the first key off the dictionary listing. There’s lots of great stuff inside of the collections
library. The next one I’m going to show you is the defaultdict
class.
04:18 This is a dictionary that allows you to specify the behavior of what happens when a key that is called is missing. A common use case for this is when you need a dictionary that contains lists.
04:30 By using a default dictionary configured with an empty list, the first use of an empty key is initialized to an empty list. This means you don’t have to write the additional code checking whether or not the key exists in the dictionary, and if it doesn’t, add the key to the dictionary with an empty list and then add the item that you were intending to put in in the first place.
04:52 Let me just import that.
04:58
When you construct a defaultdict
, you pass in what the default is for the dictionary. In this case, I’m passing in the list
type.
05:08
The animals
object is now a defaultdict
that uses a list
as the default value if the keys are empty. The REPL shows you that the dictionary is currently empty.
05:20
Referencing the key "dogs"
returns an empty list. This is what defaultdict
does for you. Now if you look at animals
again, you’ll notice that the key 'dogs'
is now inside of the defaultdict
.
05:38 You can now directly address this list and append items to it.
05:47
You can even append items to a key that doesn’t exist. The first reference will create the empty list and the .append()
will work on that empty list. Here’s the resulting dictionary.
05:59
It now contains two keys—one for 'dogs'
, one for 'cats'
, both of which contain lists, 'dogs'
having ['Spot']
and 'cats'
having ['Mittens']
.
06:11
Let me just add one more thing to "dogs"
here, and then you can reference the key specifically and get the list resulting. You can initialize your defaultdict
with just about anything, although the list is the most common thing I’ve seen out there in code.
06:28
That’s all for now. In the next lesson, I’ll show you the ChainMap
and the MappingProxyType
classes.
Become a Member to join the conversation.