[ACCEPTED]-Accessing key in factory of defaultdict-defaultdict

Accepted answer
Score: 28

__missing__ of defaultdict does not pass key to factory function.

If 4 default_factory is not None, it is called without arguments to provide a default 3 value for the given key, this value is inserted 2 in the dictionary for the key, and returned.

Make 1 your own dictionary class with custom __missing__ method.

>>> class MyDict(dict):
...     def __init__(self, factory):
...         self.factory = factory
...     def __missing__(self, key):
...         self[key] = self.factory(key)
...         return self[key]
... 
>>> d = MyDict(lambda x: -x)
>>> d[1]
-1
>>> d
{1: -1}
Score: 6

Unfortunately not directly, as defaultdict 4 specifies that default_factory must be called 3 with no arguments:

http://docs.python.org/2/library/collections.html#collections.defaultdict

But it is possible to 2 use defaultdict as a base class that has 1 the behavior you want:

class CustomDefaultdict(defaultdict):
    def __missing__(self, key):
        if self.default_factory:
            dict.__setitem__(self, key, self.default_factory(key))
            return self[key]
        else:
            defaultdict.__missing__(self, key)

This works for me:

>>> a = CustomDefaultdict(factory)
>>> a
defaultdict(<function factory at 0x7f0a70da11b8>, {})
>>> print a['aaa']
{'key-md5': '47bce5c74f589f4867dbd57e9ca9f808'}
>>> print a['bbb']
{'key-md5': '08f8e0260c64418510cefb2b06eee5cd'}
Score: 0

In several cases where I wanted a defaultdict 5 with the key in the factory, I found an 4 lru_cache also solved my problem:

import functools

@functools.lru_cache(maxsize=None)
def use_func_as_dict(key='') # Or whatever type
    with open(key, 'r') as ifile:
        return ifile.readlines()

f1 = use_func_as_dict('test.txt')
f2 = use_func_as_dict('test2.txt')
# This will reuse the old value instead of re-reading the file
f3 = use_func_as_dict('test.txt')
assert f3 is f1

This actually makes 3 more sense theoretically, since you're after 2 a function of the input rather than a consistent 1 dummy fallback.

More Related questions