Types of Dictionaries in Python
A topic on dictionaries was something I wanted to pen down as soon as I learned about its importance, especially in Python language. Without further ado, let's make a quick tour of this omnipresent data structure.
There are 5 different types of specialized dictionaries in python. They all are present in collections
module.
0. defaultdict: as the name says, we can give a default value for the currently nonexisting key.
- OrderedDict: keys ordering are guaranteed (based on insertion order)
- Counter: calculate frequency of items. The item must be able to be a key in a dictionary (hashable).
- ChainMap: a way to group together different dictionaries, order matters
- UserDict: base class to create a custom dictionary
Ok, let’s see these dictionaries in action.
A usual way to instantiate a dictionary in Python is {}
or dict()
. These are the special dictionaries for different use cases.
0. defaultdict
What do you think the value of the key e
would be? Let’s check the output:
defaultdict(<class 'int'>, {'a': 97, 'b': 98, 'c': 99, 'e': 0})
Look, it’s 0
. That’s because we are accessing a key that does not have a value set, hence defaultdict
sets to the default value. In this case 0
. The int
is callable and its default value is 0
. Hence, if you do int()
, it gives 0
.
Can you think of a similar scenario of setting default values in a normal dictionary?
The output is :
{'N': 1, 'a': 3, 'm': 1, 's': 1, 'k': 1, 'r': 1}
Line # 4 is basically setting the default value 0
if the value is not present. defaultdict makes having to set default value just once.
- OrderedDict
If an order of keys is needed, then lo and behold, Python 3.6 and above have that ready for you.
The output is:
Ordered Dict
OrderedDict([('uno', 1), ('dos', 2), ('tres', 3), ('cuatro', 4), ('cinco', 5)])After move_to_end
OrderedDict([('dos', 2), ('tres', 3), ('cuatro', 4), ('cinco', 5), ('uno', 1)])After move_to_end is False
OrderedDict([('uno', 1), ('dos', 2), ('tres', 3), ('cuatro', 4), ('cinco', 5)])
We also used move_to_end
method to move items to the end of the dictionary or to the beginning.
Does this sound similar to some other data structure? Hello, deque
. Also resides in the collections
module. The corresponding deque
's method of move_to_end
and move_to_end
with last=False
are pop
and popleft
respectively.
2. Counter
You may have come across scenarios where you needed to calculate the frequency of items, for example calculating the frequency of words in a sentence. Python has Counter
dictionary to do that job for you.
The output is:
Counter dict
Counter({'peace': 2, 'prevail': 2, 'on': 2, 'earth.': 2, 'Let': 1, 'and': 1, 'love': 1, 'May': 1})
With that magic, the Counter
the dictionary has also many methods such as update
, subtract
with another dictionary. Check them out!
We can also use min
and max
function to get a key that has a minimum and maximum frequency.
3. ChainMap
You may have come across scenarios where you needed to combine a disparate collection of items. We have chain
methods from itertools
module to chain lists, what about dictionaries? We have ChainMap.
The output is:
ChainMap dict
ChainMap({'Daffodil': 'gradient yellow', 'Primrose': 'gradient crimson', 'Iris': 'purple'}, {'Allum': 'purple', 'Begonia': 'gradient pink', 'Delphinium': 'varied color', 'Black-Eyed-Susan': 'yellow and dark brown'}, {'Aster': 'yellow and purple', 'Dianthus': 'gradient maroon', 'Black-Eyed-Susan': 'yellow and dark brown'}, {'Crocus': 'purple', 'Snowdrop': 'white', 'Primrose': 'gradient crimson'})change of color occurs only in first occurrence
ChainMap({'Daffodil': 'gradient yellow', 'Primrose': 'gradient crimson', 'Iris': 'purple', 'Black-Eyed-Susan': 'orange and black'}, {'Allum': 'purple', 'Begonia': 'gradient pink', 'Delphinium': 'varied color', 'Black-Eyed-Susan': 'yellow and dark brown'}, {'Aster': 'yellow and purple', 'Dianthus': 'gradient maroon', 'Black-Eyed-Susan': 'yellow and dark brown'}, {'Crocus': 'purple', 'Snowdrop': 'white', 'Primrose': 'gradient crimson'})dictionaries in the chain maps are references to the original dictionary
flowers.maps[1] == summer_flowers => True
The order you added dictionaries to the ChainMap
matters. The child is the first dictionary and the rest are the parents.
The dictionaries in the ChainMap
are the reference to the original dictionaries. If you made an update to a key, only a first occurrence is updated. You can see the example with Black-Eyed-Susan
the flower which occurs in both summer and autumn season gets updated only in summer_flower
dictionary.
4. UserDict
There are times where you want your own custom dictionary, for example having your own set of allowed keys for the dictionary. We could subclass from a normal dict
class, however, setting and getting items does not guarantee use of the dunder method __setitem__
, __getitem__
. Hence, Python provides UserDict
.
The output is:
SpringBouquet dict
{'Daffodil': 2, 'Glory of the Snow': 3}setting not spring flower should raise an error
Traceback (most recent call last):
File "/Users/dichha/Documents/Projects/medium/dict/ex.py", line 93, in <module>
sb['crocus'] = 4
File "/Users/dichha/Documents/Projects/medium/dict/ex.py", line 82, in __setitem__
raise KeyError(f'Flower {key} is not a spring flower. Sorry.')
KeyError: 'Flower crocus is not a spring flower. Sorry.'
See, we made our own custom dictionary! 😍
That’s all I have for this post on dictionaries! I hope it was helpful to know about the different types of specialized dictionaries we have in Python, use them accordingly, and of course, explore more.
Thank you for reading. Happy New Year 2022! 🦋
Inspiration:
You can support me on Patreon.