我想跟踪我已经在字典中处理过的key-value
对(或者其他更好的东西),其中key
是一些输入,而value
是一些复杂函数/计算的返回输出。主要目的是防止再次执行相同的过程,如果我希望获得之前看到的键的值。我已经尝试使用setdefault
和get
来解决这个问题,但无论密钥是否存在于字典中,我调用的函数最终都会被执行。
示例代码:
def complex_function(some_key):
"""
Complex calculations using some_key
"""
return some_value
# Get my_key's value in my_dict. If my_key has not been seen yet,
# calculate its value and set it to my_dict[my_key]
my_value = my_dict.setdefault(my_key, complex_function(my_key))
无论complex_function
是my_key
,{p> my_dict
最终都会被执行。我也尝试使用my_dict.get(my_key, complex_function(my_key))
得到相同的结果。目前,这是我的固定解决方案:
if my_key not in my_dict:
my_dict[my_key] = complex_function(my_key)
my_value = my_dict[my_key]
以下是我的问题。首先,为此目的使用字典正确的方法?第二,我正确使用setdefault
吗?第三,我目前是否解决了这个问题? (如果my_dict[my_key]
不存在,我最终会拨打my_key
两次)
答案 0 :(得分:3)
所以我继续采取文森特建议使用装饰师。
以下是新修补程序的样子:
import functools
@functools.lru_cache(maxsize=16)
def complex_function(some_input):
"""
Complex calculations using some_input
"""
return some_value
my_value = complex_function(some_input)
据我所知,到目前为止,lru_cache
使用字典来缓存结果。此字典中的key
引用装饰函数(some_input
)的参数,value
引用装饰函数(some_value
)的返回值。因此,如果函数使用之前传递过的参数调用,它将只返回装饰器字典中引用的值,而不是运行函数。如果没有看到参数,则函数正常进行,此外,装饰器在其字典中创建新的键值对。
我现在将maxsize
设置为16,因为我不希望some_input
代表超过10个唯一值。需要注意的一点是,装饰函数的参数必须是不可变和可散列的,因为它使用参数作为其字典的键。
答案 1 :(得分:0)
original_dict = {"a" : "apple", "b" : "banana", "c" : "cat"}
keys = a.keys()
new_dict = {}
对于您现在访问的每个密钥,请运行以下命令:
new_dict[key] = value
要检查您是否已访问密钥,请运行以下代码:
#if new_key is not yet accessed
if not new_key in new_dict.keys() :
#read the value of new_key from original_dict and write to new_dict
new_dict[new_key] = original_dict[new_key]
我希望这会有所帮助
答案 2 :(得分:0)
您当前的解决方案很好。您正在创建稍微多一点的工作,但是当密钥已经存在时,显着减少了计算工作量。
然而,defaultdict
几乎就是你所需要的。通过稍微修改它,我们可以使其完全按照您的意愿工作。
from collections import defaultdict
class DefaultKeyDict(defaultdict):
def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = value = self.default_factory(key)
return value
d = DefaultKeyDict(lambda key: key * 2)
assert d[1] == 2
print(d)