背景:
假设我有一个功能(当然,实际上这将是一个更复杂的功能):
def f(x):
return str(x)
如果我想存储值以避免不必要的重新计算,我可以像这样创建一个dict
:
my_dict = {x: f(x) for x in range(5)}
但是如果我事先不知道我可能需要哪些值,例如10
,my_dict[10]
显然会生成KeyError
。
解决这个问题的方法可能是:
my_dict = {}
def get_value(x):
if x not in my_dict:
my_dict[x] = f(x)
return my_dict[x]
get_value(10)
问题:
这似乎与defaultdict
非常相似:有没有办法使直观(但破坏)my_dict = defaultdict(f)
工作,即当一个键x
不存在时,它应该调用{{1}而不是f(x)
来创建默认值?
答案 0 :(得分:3)
基于the docs,您可以通过继承defaultdict
并覆盖__missing__
来获得所需的行为:
from collections import defaultdict
class betterdefault(defaultdict):
def __missing__(self, key):
return self.default_factory(key)
现在,你想要通过一些额外的逻辑来实现这一点,例如,如果KeyError
为None,则抛出self.default_factory
,就像他们在文档中提到的那样。希望这能指出你正确的方向。
这里快速demo
答案 1 :(得分:2)
您可以构建自己的dict
数据类型。在您的情况下,__missing__
会有所帮助。如果没有密钥,__missing__
方法会触发您的自定义工作。下面是一个简单的例子。
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}
还要注意UserDict
是字典对象的包装器,这使您可以轻松地对字典数据类型进行子类化。
查看官方文档。