UserDict, UserList and UserString – Collections in Python

In Python UserDict, UserList and UserString are classes in the collections module. These classes provide a way to create custom dictionary, list, and string-like objects by inheriting from them. These classes are useful when we need to extend or modify the behavior of the built-in types like dictionaries, lists, and strings, but still have their basic structure and functionalities.

UserDict

UserDict is a wrapper around the dictionary objects. UserDict class can be used as a base class to create custom dictionary-like objects.

Key Properties

  • UserDict behaves like a dictionary. This class inherits basic properties of original dictionary class.
  • It doesn’t modify the original dict class, but provides a way to customize dictionary behavior by subclassing.

Create UserDict object

Syntax => userdict_object = UserDict(dict=None, **kwargs)

  • UserDict has the __init__ method which supports two arguments dict and kwargs.
  • dict is the dictionary based on which UserDict object is created. This is an optional argument. By default dict value is None.
  • kwargs are the number of key-value arguments provided, based on which UserDict object will be created. The kwargs passed in __init__ are unpacked into the dictionary, making it easy to initialize custom dictionary.
from collections import UserDict

# Scenario 1 - create empty UserDict dictionary
print("create empty UserDict dictionary")
userdict_empty_dict = UserDict()  # Create empty UserDict object
print(userdict_empty_dict)        # Elements in UserDict object
print(type(userdict_empty_dict))  # Class type of UserDict object

# Scenario 2 - access data from the UserDict dictionary
print("access data from the UserDict dictionary")
course_dict = {'c1':'AWS','c2':'Python','c3':'ML'}
userdict_course_dict = UserDict(course_dict) # UserDict object with initial dictionary
print(userdict_course_dict)                  # Elements in UserDict object
print(userdict_course_dict.data)             # data attribute on UserDict object
  • In first scenario, we are using UserDict() to create an empty UserDict object. Default value for dict=None will be used.
  • In second scenario, we are using UserDict(course_dict) to create UserDict object passing dictionary elements.
  • userdict_course_dict.data returns the elements in the object.

Program Output

create empty UserDict dictionary
{}                               # Empty object
<class 'collections.UserDict'>   # Class type of UserDict object

access data from the UserDict dictionary
{'c1': 'AWS', 'c2': 'Python', 'c3': 'ML'} # Elements in UserDict object
{'c1': 'AWS', 'c2': 'Python', 'c3': 'ML'} # data elements in UserDict object

UserDict Program

In this program, we will perform following operations using UserDict class.

  • We will create a custom class Courses using the UserDict as base class. Courses class will have method to perform add, update and remove operations.
  • We will create Courses class object using dictionary elements.
  • We will perform add, update and remove operations on Courses class object.
from collections import UserDict

print("UserDict demonstration using a program")
class Courses(UserDict):     # Class created with UserDict
	def upsertCourse(self, key, course):
		self.data[key] = course
	
	def removeCourse(self, key):
		raise RuntimeError("remove of course is not allowed")

# main code to create object of class
shbytes_courses = Courses({1:"Python", 2:"AWS", 3:"Azure"}) # Courses object with dictionary elements
print("Initial courses list - ", shbytes_courses.data)      # Elements in Courses object

# add course
shbytes_courses.upsertCourse(4, "DevOps")      # Add key-value in Courses object
print("Courses after addition - ", shbytes_courses.data)   # Elements after adding key-value

# update course
shbytes_courses.upsertCourse(4, "ML")         # Update key-value in Courses object
print("Courses after update - ", shbytes_courses.data)    # Elements after updating key-value

# remove course
try:
	shbytes_courses.removeCourse(4)   # Try removing element with key from Courses object
except RuntimeError as err:           # removeCourse() raise RuntimeError
	print("error", err)
print("Courses after remove - ", shbytes_courses.data) # Elements after trying removing key

Program Output

UserDict demonstration using a program
Initial courses list -  {1: 'Python', 2: 'AWS', 3: 'Azure'} # Original elements in the Courses object

Courses after addition -  {1: 'Python', 2: 'AWS', 3: 'Azure', 4: 'DevOps'} # Element key 4 added

Courses after update -  {1: 'Python', 2: 'AWS', 3: 'Azure', 4: 'ML'}       # Element key 4 updated

error remove of course is not allowed
Courses after remove -  {1: 'Python', 2: 'AWS', 3: 'Azure', 4: 'ML'}       # Elements after trying remove

UserList

UserList is a wrapper around the list objects. UserList class can be used as a base class to create custom list-like objects.

Key Properties

  • UserList behaves like a list. This class inherits basic properties of original list class.
  • It doesn’t modify the original list class, but provides a way to customize list behavior by subclassing.
  • Custom behaviors can be added for operations like adding, removing, or modifying elements.

Create UserList object

Syntax => userlist_object = UserList(initlist=None)

  • UserList has the __init__ method which supports one argument initlist.
  • initlist is the initialized list based on which UserList object is created. This is an optional argument. By default initlist value is None.
from collections import UserList

# create empty UserList list
print("create empty UserList list")
userlist_empty_list = UserList()    # Create empty UserList object
print(userlist_empty_list)          # Elements in UserList object
print(type(userlist_empty_list))    # Class type of UserList object

# create UserList list with initialized data
print("create UserList list with initialized data")
course_list = ['AWS','Python','ML','DevOps']
userlist_course_list = UserList(course_list) # UserList object with initial list
print(userlist_course_list)      # Elements in UserList object
print(userlist_course_list.data) # data attribute on UserList object
  • In first scenario, we are using UserList() to create an empty UserList object. Default value for initlist=None will be used.
  • In second scenario, we are using UserList(course_list) to create UserList object passing list elements.
  • userlist_course_list.data returns the elements in the object.

Program Output

create empty UserList list
[]   # Empty object
<class 'collections.UserList'>  # Class type of UserList object

create UserList list with initialized data
['AWS', 'Python', 'ML', 'DevOps'] # Elements in UserList object
['AWS', 'Python', 'ML', 'DevOps'] # data elements in UserList object

UserList Program

In this program, we will perform following operations using UserList class.

  • We will create a custom class Courses using the UserList as base class. Courses class will have method to perform add, update and remove operations.
  • We will create Courses class object using initial list elements.
  • We will perform add, update and remove operations on Courses class object.
from collections import UserList

print("UserList demonstration using a program")
class Courses(UserList):   # Class created with UserList
	def addCourse(self, course):
		self.data.append(course)
	
	def updateCourse(self, course1, course2):
		for index, item in enumerate(self.data):
			if item == course1:
				self.data[index] = course2
	
	def removeCourse(self, course):
		raise RuntimeError("remove of course is not allowed")

# main code to create object of class
shbytes_courses = Courses(["Python","AWS","DevOps","ML","Azure"]) # Courses object with list elements
print("Initial courses - ", shbytes_courses.data) # Elements in Courses object

# add course for shbytes
shbytes_courses.addCourse("HTML")  # Add element in Courses object
print("Courses after addition - ", shbytes_courses.data) # Elements in Courses object after adding

# update course for shbytes
shbytes_courses.updateCourse("HTML", "PHP") # Update element in Courses object
print("Courses after update - ", shbytes_courses.data) # Elements in Courses object after updating

# remove course for shbytes
try:
	shbytes_courses.removeCourse("PHP") # Remove element in Courses object
except RuntimeError as err:
	print("error", err)
print("Courses after remove - ", shbytes_courses.data) # Elements in Courses object after trying removing

Program Output

UserList demonstration using a program
Initial courses -  ['Python', 'AWS', 'DevOps', 'ML', 'Azure'] # Original elements in the Courses object

Courses after addition -  ['Python', 'AWS', 'DevOps', 'ML', 'Azure', 'HTML'] # Element added

Courses after update -  ['Python', 'AWS', 'DevOps', 'ML', 'Azure', 'PHP'] # Element updated

error remove of course is not allowed
Courses after remove -  ['Python', 'AWS', 'DevOps', 'ML', 'Azure', 'PHP'] # Elements after trying remove

UserString

UserString is a wrapper around the string objects. UserString class can be used as a base class to create custom string-like objects where we can add or override methods for strings.

Key Properties

  • UserString behaves like a string. This class inherits basic properties of original string class.
  • It doesn’t modify the original string class, but provides a way to customize string behavior by subclassing.
  • Custom behaviors can be added for operations like adding, removing, or modifying elements.
  • We can customize behaviors such as case conversions, concatenation, etc.

Create UserString object

Syntax => userstring_object = UserString(seq)

  • UserString has the __init__ method which supports one argument seq.
  • seq is the initial sequence (string) based on which UserString object is created.
from collections import UserString

# create empty UserString string
print("create empty UserString string")
userstring_empty = UserString("")  # Create empty UserString object
print(userstring_empty)            # Elements in UserString object
print(type(userstring_empty))      # Class type of UserString object

# create UserString string with initialized data
print("create UserString string with initialized data")
courses = "AWS,Python,ML"
userstring_courses = UserString(courses) # UserString object with initial string elements
print(userstring_courses)                # Elements in UserString object
print(userstring_courses.data)           # data attribute on UserString object
  • In first scenario, we are using UserString() to create an empty UserString object.
  • In second scenario, we are using UserString(courses) to create UserString object passing string sequence.
  • userstring_courses.data returns the elements in the object.

Program Output

create empty UserString string
    # Empty string object
<class 'collections.UserString'>  # Class type of UserString object

create UserString string with initialized data
AWS,Python,ML  # Elements in UserString object
AWS,Python,ML  # data elements in UserString object

UserString Program

In this program, we will perform following operations using UserString class.

  • We will create a custom class Courses using the UserString as base class. Courses class will have method to perform add, update and remove operations.
  • We will create Courses class object using initial string sequence.
  • We will perform add, update and remove operations on Courses class object.
from collections import UserString

print("program to create mutable string")
class Courses(UserString):       # Class created with UserString
	def addCourse(self, course):
		self.data += course
	
	def updateCourse(self, course1, course2):
		self.data = self.data.replace(course1, course2)
	
	def removeCourse(self, course):
		self.data = self.data.replace(course, "")

# main code to create object of class
shbytes_courses = Courses("Python,AWS,DevOps,ML,Azure") # Courses object with string sequence
print("Initial courses - ", shbytes_courses.data) # Elements in Courses object

# add course for shbytes
shbytes_courses.addCourse("HTML") # Add element in Courses object
print("Courses after addition - ", shbytes_courses.data) # Elements in Courses object after adding string

# update course for shbytes
shbytes_courses.updateCourse("HTML", "PHP") # Update element in Courses object
print("Courses after update - ", shbytes_courses.data) # Elements in Courses object after updating string

# remove course for shbytes
shbytes_courses.removeCourse("PHP") # Remove element in Courses object
print("Courses after remove - ", shbytes_courses.data) # Elements in Courses object after removing string

Program Output

program to create mutable string
Initial courses -  Python,AWS,DevOps,ML,Azure # Original elements in the Courses object

Courses after addition -  Python,AWS,DevOps,ML,AzureHTML # String element added

Courses after update -  Python,AWS,DevOps,ML,AzurePHP # String element updated

Courses after remove -  Python,AWS,DevOps,ML,Azure # String element removed

Summary

In this article, we learned about UserDict, UserList and UserString collections in Python. Following topics were discussed:

Code – Github Repository

All code snippets and programs for this article and for Python tutorial, can be accessed from Github repository – Comments and Docstring in Python.

Python Topics


Interview Questions & Answers

Q: How does UserDict differ from a regular dictionary in Python?

UserDict is a part of the collections module and is a wrapper class around the standard dict. While both have similar functionality, the main difference is that UserDict stores its data in an internal dictionary self.data, and is designed to be easier to subclass. It allows developers to modify or extend the behavior of a dictionary without affecting the behavior of the built-in dict.

For instance, if we override a method in UserDict, we don’t need to worry about affecting other uses of dict in our code, whereas overriding the built-in dict can have far-reaching effects.

Q: Explain practical use case for UserDict, UserList, or UserString?

UserDict can be used for logging or validating dictionary changes. Suppose we are building a system where any changes to the dictionary (adding, modifying, or deleting keys) need to be logged. We could subclass UserDict and override the necessary methods (__setitem__, __delitem__, etc.) to include logging functionality.

For UserList, we could create a list class that only accepts specific data types or enforces certain rules, such as a list of unique elements.

UserString can be used to create specialized string manipulations, like always ensuring the string is in uppercase or performing validation.

Q: What are the main methods in UserDict, UserList, and UserString that need to override when subclassing?

UserDict

  • __setitem__ => Override to change the behavior when setting an item.
  • __getitem__ => Override to modify how an item is retrieved.
  • __delitem__ => Override to change the behavior when an item is deleted.
  • update => Override to modify how dictionaries are updated.

UserList

  • append => Override to control what is added to the list.
  • __setitem__ => Override to change the behavior when modifying an element.
  • __getitem__ => Override to modify how elements are accessed.

UserString

  • __str__ => Override to modify how the string is represented.
  • __add__, __mul__ => Override to control how the string interacts with other strings or numbers.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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