Python Defaultdict – Int and List as a Default Factory


1. Python Defaultdict

Dictionaries are an important part of Python. They are containers to hold key-value pairs. In today’s lesson, we will look at Python defaultdict, a subclass of the built-in dict class. So let’s start with defaultdict Python 3 tutorial.

>>> issubclass(defaultdict,dict)   #You’ll need to import defaultdict from collections for this

True

introduction to Python Defaultdict

Python Defaultdict – Introduction

2. A Revision – Python Dictionaries

Before we proceed to defaultdict in Python, we suggest you read up on Python Dictionaries.

A python dictionary is a container that holds key-value pairs. Keys must be unique, immutable objects. This means that a Python tuple can be a key, but a python list can’t since it is mutable.

>>> {[1,2]:1,2:2}
Traceback (most recent call last):
File "<pyshell#355>", line 1, in <module>
{[1,2]:1,2:2}

TypeError: unhashable type: ‘list’

As you can see, a list, then, is unhashable. Let’s take a quick example to see how to define a python dictionary.

>>> mydict={'a':1,'b':2,'c':3}
>>> mydict['b']

2

We can also use the dict() function.

>>> otherdict=dict((['a',1],['b',2],['c',3]))
>>> otherdict

{‘a’: 1, ‘b’: 2, ‘c’: 3}

To get a list of keys, we use the keys() method.

>>> otherdict.keys()

dict_keys([‘a’, ‘b’, ‘c’])

But we have one problem. If the key does not exist, and we try to access it, it raises a KeyError.

>>> otherdict['d']
Traceback (most recent call last):
File "<pyshell#364>", line 1, in <module>
otherdict['d']

KeyError: ‘d’

3. Introduction to Python Defaultdict

To deal with this situation, we have defaultdict in Python. First, we must import it from Python collections module.

>>> from collections import defaultdict

Here, we use the Python defaultdict() factory function. It takes, as an argument, a function object that will return a value. Actually, if we don’t provide a value for a particular key, it will take that value for it. Let’s take a look at the syntax.

4. Python Defaultdict – Syntax

Before python defaultdict syntax, we revise python syntax.

As we discussed, we first import defaultdict from the ‘collections’ module. Let us see this Python defaultdict example.

>>> from collections import defaultdict

Next, we define a python function to return a default value for the keys we don’t initialize.

>>> def defaultvalue():
                return 0

Now, we create a Python defaultdict using the defaultdict() function. To this, we pass the function defaultvalue as a function argument. Remember, you must pass the function object, you don’t have to call it with parentheses.

>>> otherdict=defaultdict(defaultvalue)

Let’s now define values for keys ‘a’, ‘b’, and ‘c’.

>>> otherdict['a']=1
>>> otherdict['b']=2
>>> otherdict['c']=3

What if we access the value for key ‘d’? We haven’t initialized it yet.

>>> otherdict['d']

0

As you can see, it assigned it the default value we specified through function defaultvalue().

Let’s see the whole code at once now.

>>> def defaultvalue():
                return 0
>>> otherdict=defaultdict(defaultvalue)
>>> otherdict['a']=1
>>> otherdict['b']=2
>>> otherdict['c']=3
>>> otherdict['d']

0

5. Another Example of Python Defaultdict

Let’s take another python defaultdict example. We take a defaultdict in python to hold the marks of students. Also, we let the default value for marks be 35.

>>> marks=defaultdict(lambda :35)
>>> marks['Ayushi']=95
>>> marks['Gigi']=86
>>> marks['Ayushi']

95

Here, we used a Lambda Expression since all we need to do in it is to return a value. So why waste space, right? Now, if we try to access the value to a key that doesn’t exist, it saves 35 to it.

>>> marks['Oshin']

35

Finally, these are the keys to this python defaultdict now:

>>> marks.keys()
dict_keys(['Ayushi', 'Gigi', 'Oshin'])

6. More on python Defaultdict

Let’s see what happens if we return a None from the function.

>>> a=defaultdict(lambda :None)
>>> a[1]
>>> type(a[1])

<class ‘NoneType’>

What if a python exception was raised in the factory function?

>>> def defaultvalue():
                print(1/0)
                return 0
>>> a=defaultdict(defaultvalue)
>>> a[1]
Traceback (most recent call last):
File "<pyshell#386>", line 1, in <module>
a[1]
File "<pyshell#384>", line 2, in defaultvalue
print(1/0)

ZeroDivisionError: division by zero

Python defaultdict supports all operations that a regular dictionary does. These include keys() and len().

>>> dir(a)

[‘__class__’, ‘__contains__’, ‘__copy__’, ‘__delattr__’, ‘__delitem__’, ‘__dir__’, ‘__doc__’, ‘__eq__’, ‘__format__’, ‘__ge__’, ‘__getattribute__’, ‘__getitem__’, ‘__gt__’, ‘__hash__’, ‘__init__’, ‘__init_subclass__’, ‘__iter__’, ‘__le__’, ‘__len__’, ‘__lt__’, ‘__missing__’, ‘__ne__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__setitem__’, ‘__sizeof__’, ‘__str__’, ‘__subclasshook__’, ‘clear’, ‘copy’, ‘default_factory’, ‘fromkeys’, ‘get’, ‘items’, ‘keys’, ‘pop’, ‘popitem’, ‘setdefault’, ‘update’, ‘values’]

Let’s know about Exception handling in python.

a. __missing__(key)

This Python method is called by the __getitem__() method of the dict class when the requested key isn’t found.

>>> from collections import defaultdict
>>> a=defaultdict(lambda :0)
>>> a['a']=1
>>> a['b']=2
>>> a['c']=3
>>> a.__missing__('d')

0

It returned 0 here because that’s what we specified as a default value through a lambda expression to the defaultdict() factory function.

>>> a.__getitem__('a')

1

>>> a.__getitem__('e')

0

7. Using ‘list’ as a default factory

If we pass ‘list’ (without the quotes) to the defaultdict() Pytohn function, we can group a sequence of key-value pairs into a dictionary of lists. We can do this to more types as well. We’ll see another in the next section.

>>> a=[('a',1),('b',2),('c',3)]
>>> b=defaultdict(list)
>>> for i,j in a:
                b[i].append(j)              
>>> b

defaultdict(<class ‘list’>, {‘a’: [1], ‘b’: [2], ‘c’: [3]})

Let’s explain what this code does. First, we define ‘a’ as a list of tuples to hold the key-value pairs. Next, we pass ‘list’ to defaultdict(), and store this in ‘b’. This tells the interpreter that b will hold a dictionary with values that are list.

Then, we traverse on the tuples using names ‘I’ and ‘j’ with a for-loop. In this, we append j to b[i]. What this means is that we take the second value in each tuple in ‘a’, and append it to the python defaultdict for each key (first value in each tuple). For ‘c’ in the list ‘a’, as a key in the defaultdict ‘b’, we append the value 3 to the python defaultdict to that key. This is its value now.

8. Using ‘int’ as a default factory

We can tell the interpreter to create a Python dictionary of integers. Here’s how.

>>> name='Bubbles'
>>> mydict=defaultdict(int)
>>> for i in name:
                mydict[i]+=1              
>>> mydict

defaultdict(<class ‘int’>, {‘B’: 1, ‘u’: 1, ‘b’: 2, ‘l’: 1, ‘e’: 1, ‘s’: 1})

This way, we can use it as a counter. Of course, we could have done this with a regular dictionary as well. But here, we tell the interpreter that we’re going to work with only integer values.

9. Conclusion

With a subtle difference to a regular dictionary, we see that a python defaultdict is actually quite useful. It has a simple syntax as well and lets us define a default value for uninitialized keys. It also lets us tell the interpreter that we want to work with a particular type of values.

See Also- Python Namedtuple, Python OrderdDict & Python Counter

For reference

Leave a comment

Your email address will not be published. Required fields are marked *