Skip to content

Python UserDict – Custom Python Dictionaries with collections

Python UserDict - Custom Python Dictionaries with collections Cover Image

Building custom dictionaries allows you to define powerful programs. You can easily build new dictionaries that have custom behavior or new functionalities, which build on top of regular Python dictionaries. In this tutorial, you’ll learn how to use the Python collections UserDict class to create custom dictionaries. You’ll also learn how to build your own custom dictionary, by building a dictionary with case-insensitive lookups.

By the end of this tutorial, you’ll have learned the following:

  • How to build custom Python dictionaries using the UserDict class
  • How to understand common use cases for the UserDict class by building an example custom dictionary

Understanding the Python collections UserDict Class

The UserDict class has been included in Python since version 1.6, however, it was moved to the collections module in Python 3. We can use the UserDict class to inherit from a dictionary to enhance or modify its default behavior. In particular, the class simply subclasses, rather than instantiates.

This means that the class inherits from the dictionary and emulates it. The UserDict also makes the original dictionary accessible through a .data attribute.

The class created a data attribute, which stores the contents of the underlying dictionary. This allows you to build custom methods and behavior that have access to the underlying data.

Let’s see how the class is defined and how to create a simple UserDict:

# Creating a UserDict
from collections import UserDict

class Custom(UserDict):
    pass

custom_dict = Custom({'Name': 'Nik', 'Age': 33})
print(custom_dict)

# Returns:
# {'Name': 'Nik', 'Age': 33}

In the example above, we created a UserDict that doesn’t modify the behavior of the regular dictionary. This example was merely meant to illustrate that the custom dictionary inherits all default behavior from a normal Python dictionary.

Let’s now dive into an example of how to create a custom dictionary using the UserDict class.

Creating a Custom Dictionary with Python UserDict

In our previous example, we created a UserDict dictionary which didn’t modify a dictionary’s behavior at all. However, let’s dive into some more advanced use cases. We’ll create a dictionary where the look-up values are case-insensitive.

By default, Python dictionaries have unique keys, which are case-sensitive. Looking up the key 'age' is different than looking up the key of 'AGE'. If you’re not sure what capitalization your key has, this can lead to some unexpected behavior.

Let’s see how we can use the UserDict class to create a custom Python dictionary:

# Creating a Case-Insensitive Lookup in a Custom Dictionary
from collections import UserDict

class CaseInsensitiveDict(UserDict):
    def __setitem__(self, key, value):
        key = str(key).lower()
        self.data[key] = value

    def __getitem__(self, key):
        key = str(key).lower()
        return self.data[key]

custom_dict = CaseInsensitiveDict({'Name': 'Nik', 'Age': 33, 3: 3})
print(custom_dict['name'])

# Returns:
# Nik

In the example above, we have included two methods in the class. Let’s dive into how we modified our UserDict to make key lookups case-insensitive:

  1. We imported the UserDict class from the collections module
  2. We defined our class CaseInsensitiveDict which inherits from the UserDict class
  3. We then overwrote the __setitem__() method. In this case, it takes three parameters: self, the key, and the value.
    1. For the key that’s passed in, the lowercase string version is returned.
    2. Then, the underlying dictionary is accessed and the value is set to the lowercase key
  4. The __getitem__() method is overwritten as well. In this case, the method takes only self and the key.
  5. The key is transformed to its lowercase version. The underlying dictionary, data is accessed and its value is returned.
  6. We then create our first dictionary and access a lowercase key.

There’s a lot going on there! Let’s break down some of the more foundational concepts.

When we created a new class that inherits from the UserDict, we wrap a dictionary inside of the UserDict. What this means is that the original dictionary is maintained. The original dictionary is also accessible using the data attribute. Because of this, when we access the self.data value, we can access, modify, and retrieve it directly.

The .data attribute holds the original dictionary and makes accessing the data more user-friendly. Since the dictionary is subclasses, we could technically call the super() function. However, this makes our code much less readable.

Furthermore, because we’re subclassing, we can actually use any other dictionary method (that we haven’t explicitly overwritten). For example, we can use the .update() and .setdefault() methods. Because both of these methods are used to set values, our __setitem__() method will perform any necessary transformations.

Conclusion

In this tutorial, you learned how to use the UserDict class from the Python collections module to create custom Python dictionaries. You can easily build new dictionaries that have custom behavior or new functionalities, which build on top of regular Python dictionaries. In this tutorial, you learned how to use the Python collections UserDict class to create custom dictionaries. You also learned how to follow through with an example of how to create a custom UserDict, by creating a dictionary where the keys are not case-sensitive.

Additional Resources

To learn more about related topics, check out the tutorials below:

Leave a Reply

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