I want to re-implement defaultdict
myself. In principle, this feels like a really simple question, and one I might give as a “homework assignment”, but the more I dug in, the more complicated it got. My first attempt looked something like this
class DefaultDict(dict):
def __init__(self, factory):
self._factory = factory
super().__init__()
def __getitem__(self, key):
missing = object()
super_value = super().get(key, missing)
if super_value is missing:
return self._factory()
return super_value
However, this does not pass even the most trivial test suite of
x = DefaultDict(lambda: 'no value :(')
y = collections.defaultdict(lambda: 'no value :(')
x['a'] = 'hello'
y['a'] = 'hello'
print(x['a'] == y['a']) # True
print(x.get('a') == y.get('a')) # True
print(x['b'] == y['b']) # True
print(x.get('b') == y.get('b')) # False; x.get('b') is None
After some research, I found __missing__
, but an implementation using it fails the above test suite in exactly the same way
class DefaultDict(dict):
def __init__(self, factory):
self._factory = factory
super().__init__()
def __missing__(self, key):
return self._factory()
It seems to me that the only way to do this completely is to re-implement dict
methods like get
and pop
, which I don’t think should be necessary. I glanced at the C implementation of defaultdict, and as far as I can tell, it only implements __missing__
as well, so I highly doubt this is required.
What would be the most “pythonic” way to re-implement defaultdict
?