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?
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.