Search code examples
pythondictionarydefaultdict

How to automatically create value from non existing key with a function


Backgroud:

Let's say I have a function (of course in reality that would be a more complex function):

def f(x):
    return str(x)

If I want to store values to avoid unnecessary recomputation, I can create a dict like this:

my_dict = {x: f(x) for x in range(5)}

But then if I don't know in advance which values I may need, for example 10, my_dict[10] obviously generates a KeyError.

One way around this could be:

my_dict = {}
def get_value(x):
    if x not in my_dict:
        my_dict[x] = f(x)
    return my_dict[x]

get_value(10)

Question: This seems very similar to defaultdict: is there a way to make the intuitive (but broken) my_dict = defaultdict(f) work, i.e. when a key x doesn't exist, it should call f(x) instead of f() to create the default value?


Solution

  • you can build your own dict data type. in your case, __missing__ will help. if there is no key, __missing__ method triggers your custom work. below is a simple example.

    from collections import UserDict
    class MyDict(UserDict):
        def __missing__(self, key):
            self[key] = 2*key
            return self[key]
    
    if __name__ == '__main__': # test
        a = MyDict((x, 2*x) for x in range(5))
        print(a)
        # {0: 0, 1: 2, 2: 4, 3: 6, 4: 8}
        a[5]
        # 10
        print(a)
        # {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5:10}
    

    also note that UserDict is a wrapper around dictionary objects, making you comfortable to subclassing the dictionary data types.

    check the official docs.