How to Make a Python Miltidict Class
In my previous post, I showed how to make a Python class immutable. This time around I will show you my attempt at making a "Multidict" class that behaves like a dictionary but can hold multiple values for each key. I accomplish this behavior by first inheriting the built in dict object and then changing some key methods to store more than one value per key.
By inheriting dict, we get a lot of the behaviors that we want for our Multidict. The following methods are all dict methods that we need to override in order to stop old values from getting replaced with new ones and instead stores all values for each key in a list.
class Multidict(dict):
The __setitem__ method controls the key assignment behavior which we need to change to not override the previous value but instead add a new value to the list of values if the key already exists.
def __setitem__(self, key, value):
if key in self:
self[key].append(value)
else:
dict.__setitem__(self, key, [value])
Dictionaries have a method called update that allows you to pass in either an iterable object or key word arguments (kwargs) in order to add all of the pairs to the dictionary. This is the same behavior we want to use when we initialize our Multidict so I wrote the update method then call it in __init__ in order to not repeat myself.
def update(self, iterable=(), **kwargs):
"""add kwargs or tuple iterable"""
if iterable:
if type(iterable) == dict:
iterable = iterable.items()
for key,val in iterable:
self[key] = val
if kwargs:
for key,val in kwargs.items():
self[key] = val
def __init__(self, iterable=(), **kwargs):
self.update(iterable, **kwargs)
def __delitem__(self, key):
if len(self[key]) > 1:
del self[key][0]
else:
dict.__delitem__(self, key)
For pop and popitem we also want to just affect the first item if there are more than one value for a key.
def pop(self, key):
if len(self[key]) > 1:
temp = self[key][0]
del self[key]
return temp
return dict.pop(self, key)
def popitem(self, key):
if len(self[key]) > 1:
temp = key, [self[key][0]]
del self[key][0]
return temp
return dict.popitem(self, key)
def values(self):
return [val for vals in dict.values(self) for val in vals]
Inheriting dict
By inheriting dict, we get a lot of the behaviors that we want for our Multidict. The following methods are all dict methods that we need to override in order to stop old values from getting replaced with new ones and instead stores all values for each key in a list.class Multidict(dict):
__setitem__ Methods
The __setitem__ method controls the key assignment behavior which we need to change to not override the previous value but instead add a new value to the list of values if the key already exists.
def __setitem__(self, key, value):
if key in self:
self[key].append(value)
else:
dict.__setitem__(self, key, [value])
__init__ and update Method
def update(self, iterable=(), **kwargs):
"""add kwargs or tuple iterable"""
if iterable:
if type(iterable) == dict:
iterable = iterable.items()
for key,val in iterable:
self[key] = val
if kwargs:
for key,val in kwargs.items():
self[key] = val
def __init__(self, iterable=(), **kwargs):
self.update(iterable, **kwargs)
__delitem__ Method
My __delitem__ method prevents all values from being deleted when there are more than one value stored for the key. It instead deletes the first value while leaving the rest. If only one value is stored, it uses the old dict __delitem__ method.def __delitem__(self, key):
if len(self[key]) > 1:
del self[key][0]
else:
dict.__delitem__(self, key)
pop and popitem Methods
For pop and popitem we also want to just affect the first item if there are more than one value for a key.def pop(self, key):
if len(self[key]) > 1:
temp = self[key][0]
del self[key]
return temp
return dict.pop(self, key)
def popitem(self, key):
if len(self[key]) > 1:
temp = key, [self[key][0]]
del self[key][0]
return temp
return dict.popitem(self, key)
values Method
In order for our values method to output a list of just our values, we need to flatten out all our lists inside our Multidict keys.def values(self):
return [val for vals in dict.values(self) for val in vals]
Awesome job, super useful. For more info, visit this link: SEO Agency in Chennai
ReplyDeleteThis article demonstrates how to build a custom Multidict class in Python by extending the built-in dict object and overriding methods such as __setitem__, update, pop, and values. By allowing multiple values to be stored under the same key, it showcases the flexibility of Python's object-oriented programming features and how built-in data structures can be customized to meet specific application requirements.
ReplyDeleteUnderstanding inheritance, magic methods, and custom data structures is essential for writing reusable and efficient Python applications. Developers can strengthen these object-oriented programming concepts through Python Online Course, where they can learn classes, inheritance, special methods, and advanced Python programming with practical examples.
Building custom collection classes also improves problem-solving skills and helps developers design scalable software components for real-world applications. Readers can further enhance their programming expertise through Python Online Training, which covers object-oriented design, Python best practices, and application development techniques.
ReplyDeleteFor readers interested in exploring modern Python libraries, frameworks, and programming concepts, Python Training provides valuable insights into the Python ecosystem and practical development techniques.
ReplyDelete