[英]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: 如果我想存储值以避免不必要的重新计算,我可以创建一个像这样的
dict
:
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
. 不过,如果我不事先知道哪些值我可能需要,例如
10
, my_dict[10]
显然产生一个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? 问题:这看起来与
defaultdict
非常相似:有没有办法使直观(但破坏) my_dict = defaultdict(f)
工作,即当一个键x
不存在时,它应该调用f(x)
而不是f()
创建默认值?
Based on the docs , you might be able to get the behavior you want by subclassing defaultdict
and overriding __missing__
: 根据文档 ,您可以通过
__missing__
defaultdict
并覆盖__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. 现在,你想要充实说出来一点点额外的逻辑,如抛出
KeyError
,如果self.default_factory
是无,这样的东西,他们在文档提到。 Hope this points you in the right direction. 希望这能指出你正确的方向。
you can build your own dict
data type. 您可以构建自己的
dict
数据类型。 in your case, __missing__
will help. 在你的情况下,
__missing__
将有所帮助。 if there is no key, __missing__
method triggers your custom work. 如果没有密钥,
__missing__
方法会触发您的自定义工作。 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. 另请注意,
UserDict
是字典对象的包装器,使您可以轻松地对字典数据类型进行子类化。
check the official docs. 查看官方文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.