阻止评估现有密钥

时间:2015-12-21 18:06:13

标签: python dictionary

我想跟踪我已经在字典中处理过的key-value对(或者其他更好的东西),其中key是一些输入,而value是一些复杂函数/计算的返回输出。主要目的是防止再次执行相同的过程,如果我希望获得之前看到的键的值。我已经尝试使用setdefaultget来解决这个问题,但无论密钥是否存在于字典中,我调用的函数最终都会被执行。

示例代码:

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_functionmy_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两次)

3 个答案:

答案 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)