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, ie when a key x
doesn't exist, it should call f(x)
instead of f()
to create the default value?
Based on the docs , you might be able to get the behavior you want by subclassing defaultdict
and overriding __missing__
:
from collections import defaultdict
class betterdefault(defaultdict):
def __missing__(self, key):
return self.default_factory(key)
Now, you'd want to flesh that out with a little extra logic, eg throw KeyError
if self.default_factory
is None, stuff like that which they mention in the docs. Hope this points you in the right direction.
Here's a quick demo
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.