w3resource

Implementing a Self-Nesting Python Dictionary with Unlimited Depth


83. Custom Dictionary with Default Factory

Write a Python program to create a custom dictionary class that allows for nested dictionary creation on the fly, similar to collections.defaultdict but with unlimited nesting depth.

Solution:

Python Code:

# Define a custom dictionary class that supports nested dictionary creation on the fly.
class NestedDefaultDict:
    """
    A custom dictionary class that allows for nested dictionary creation on the fly,
    similar to collections.defaultdict but with unlimited nesting depth.
    """
    # Initialize the NestedDefaultDict with an empty dictionary to store data.
    def __init__(self):
        self.data = {}
    
    # Define the behavior for accessing items using the `[]` operator.
    def __getitem__(self, key):
        # If the key does not exist in the dictionary, create a new NestedDefaultDict for it.
        if key not in self.data:
            self.data[key] = NestedDefaultDict()
        # Return the value associated with the key (either an existing value or a new NestedDefaultDict).
        return self.data[key]
    
    # Define the behavior for setting items using the `[]` operator.
    def __setitem__(self, key, value):
        # Assign the given value to the specified key in the dictionary.
        self.data[key] = value
    
    # Define the string representation of the NestedDefaultDict for debugging or printing.
    def __repr__(self):
        # Return the string representation of the internal dictionary.
        return repr(self.data)
    
    # Convert the NestedDefaultDict to a regular dictionary recursively.
    def to_dict(self):
        """Convert the NestedDefaultDict to a regular dictionary recursively."""
        # Initialize an empty dictionary to store the converted result.
        result = {}
        # Iterate over each key-value pair in the internal dictionary.
        for key, value in self.data.items():
            # If the value is another NestedDefaultDict, recursively convert it to a regular dictionary.
            if isinstance(value, NestedDefaultDict):
                result[key] = value.to_dict()
            else:
                # Otherwise, directly assign the value to the result dictionary.
                result[key] = value
        # Return the fully converted regular dictionary.
        return result

# Example usage of NestedDefaultDict
# Create an instance of NestedDefaultDict.
nested = NestedDefaultDict()

# Dynamically create nested keys and assign values to them.
# This creates a nested structure: {'users': {'lio': {'profile': {'email': '[email protected]', 'age': 30}}}}
nested['users']['lio']['profile']['email'] = '[email protected]'
nested['users']['lio']['profile']['age'] = 30

# Add another user and their settings dynamically.
# This creates a nested structure: {'users': {'zuzka': {'profile': {'email': '[email protected]'}, 'settings': {'notifications': True}}}}
nested['users']['zuzka']['profile']['email'] = '[email protected]'
nested['users']['zuzka']['settings']['notifications'] = True

# Convert the NestedDefaultDict to a regular dictionary for display purposes.
# The `to_dict` method ensures the nested structure is preserved in a standard dictionary format.
regular_dict = nested.to_dict()

# Print the resulting regular dictionary to verify the structure.
print(regular_dict)

Output:

{'users': {'lio': {'profile': {'email': '[email protected]', 'age': 30}}, 'zuzka': {'profile': {'email': '[email protected]'}, 'settings': {'notifications': True}}}}

Explanation of Each Line:

  • Class Definition : Defines a custom class NestedDefaultDict to support dynamic nested dictionary creation.
  • Initialization : Initializes the NestedDefaultDict with an empty dictionary (self.data) to store key-value pairs.
  • Get Item Behavior : Implements the __getitem__ method to allow accessing keys using []. If a key doesn't exist, it creates a new NestedDefaultDict for that key.
  • Set Item Behavior : Implements the __setitem__ method to allow assigning values to keys using [].
  • String Representation : Implements the __repr__ method to provide a string representation of the internal dictionary for debugging or printing.
  • Recursive Conversion : Implements the to_dict method to recursively convert the NestedDefaultDict into a standard Python dictionary.
  • Conversion Logic : Iterates through all key-value pairs in the internal dictionary, converting nested NestedDefaultDict instances into regular dictionaries.
  • Example Usage : Demonstrates how to use the NestedDefaultDict class to dynamically create nested structures.
  • Dynamic Key Assignment : Assigns values to deeply nested keys without explicitly creating intermediate dictionaries.
  • Conversion to Regular Dict : Converts the NestedDefaultDict instance to a standard dictionary using the to_dict method.
  • Print Result : Prints the resulting regular dictionary to verify the nested structure.

Explanation - Custom Dictionary with Default Factory

  • Concept: Create a dictionary class that automatically creates nested dictionaries of unlimited depth.
  • Challenge: Override key dictionary methods to create new dictionary instances on the fly.
  • Key Skills:
    • Object-oriented programming
    • Method overriding
    • Recursive data structure design
  • Applications:
    • Building complex configuration systems
    • Creating hierarchical data structures incrementally
    • Implementing multi-level caching
    • Managing nested settings or preferences
  • Benefits:
    • Eliminates need for explicit initialization of intermediate dictionaries
    • Provides intuitive syntax for nested data access
    • Reduces boilerplate code when building complex structures

For more Practice: Solve these Related Problems:

  • Write a Python program to create a dictionary that automatically creates missing keys with a default list.
  • Write a Python function to convert a JSON object into a deeply nested `defaultdict`.
  • Write a Python class that behaves like a dictionary but triggers a callback function whenever a new key is accessed.
  • Write a Python function to create a dictionary that tracks the number of times each key is accessed.

Python Code Editor:

Previous: Dictionary-based Memoization.
Next: Dictionary Transformation Pipeline.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.