Hone logo
Hone
Problems

Implementing a defaultdict in Python

The defaultdict is a powerful container in Python that simplifies handling missing keys in dictionaries. Instead of raising a KeyError when you try to access a non-existent key, it automatically creates the key with a default value. This challenge asks you to implement the core functionality of defaultdict from scratch.

Problem Description

Your task is to create a defaultdict class that mimics the behavior of Python's built-in defaultdict. The class should take a callable (usually a function or lambda expression) as an argument during initialization. This callable will be used to provide a default value when a key is accessed that doesn't already exist in the dictionary.

What needs to be achieved:

  • Create a class named DefaultDict that inherits from dict.
  • The class constructor (__init__) should accept a callable default_factory as an argument.
  • When a key is accessed that is not present in the dictionary, the default_factory should be called with no arguments, and the result of that call should be assigned as the value for the missing key.
  • Subsequent accesses to the same key should return the stored value, not re-call the default_factory.
  • The class should otherwise behave like a standard Python dictionary.

Key requirements:

  • The default_factory must be called only when a key is accessed and doesn't exist.
  • The default_factory should not be called when setting a value for an existing key.
  • The class should support all standard dictionary operations (e.g., keys(), values(), items(), pop(), update()). While full dictionary functionality isn't required, ensure basic operations like assignment ([]) and retrieval ([]) work correctly.

Expected behavior:

When a key is accessed for the first time and it's not present, the default_factory is invoked, and the returned value is stored as the value for that key. Subsequent accesses to the same key return the stored value.

Edge cases to consider:

  • What happens if default_factory raises an exception? (While not strictly required to handle, consider the implications).
  • What happens if default_factory returns a mutable object? (Be mindful of potential side effects if multiple defaultdict instances share the same default value).
  • What happens if default_factory is None? (This is not a valid input, and should raise a TypeError).

Examples

Example 1:

Input:
default_factory = lambda: 0
my_dict = DefaultDict(default_factory)
print(my_dict['a'])
my_dict['a'] = 5
print(my_dict['a'])
print(my_dict['b'])
my_dict['b'] = 10
print(my_dict['b'])

Output:

0
5
0
10

Explanation: 'a' and 'b' are initially missing. The lambda function returns 0, which is assigned as the default value for both keys. Then, 'a' is set to 5, and 'b' is set to 10.

Example 2:

Input:
default_factory = list
my_dict = DefaultDict(default_factory)
my_dict['a'].append(1)
my_dict['a'].append(2)
print(my_dict['a'])
print(my_dict['b'])
my_dict['b'].append(3)
print(my_dict['b'])

Output:

[1, 2]
[]
[3]

Explanation: 'a' and 'b' are initially missing. The list function is called to create empty lists as default values. Then, elements are appended to the lists associated with 'a' and 'b'.

Example 3: (Edge Case)

Input:
default_factory = None
my_dict = DefaultDict(default_factory)

Output:

TypeError: first argument is not callable

Explanation: Passing None as the default_factory raises a TypeError because it's not a callable.

Constraints

  • The default_factory must be a callable (function, lambda, etc.).
  • The time complexity of accessing a key should be O(1) on average.
  • The space complexity should be proportional to the number of keys stored in the dictionary.
  • The class should be implemented in Python.

Notes

  • Focus on implementing the core functionality of providing default values for missing keys. You don't need to implement all dictionary methods.
  • Consider how the default_factory is stored and used within the class.
  • Think about how to avoid unnecessary calls to the default_factory.
  • The default_factory should be called with no arguments.
Loading editor...
python