对象属性更改时的函数缓存

时间:2019-06-20 11:13:02

标签: python

我有一个需要缓存的功能。该函数的参数尤其是对象obj。但是,我想定期更改对象obj的属性。

我尝试使用functools lru_cache

class TestObj:
    def __init__(self, number):
        self.number = number

@lru_cache(1024)
def print_number(obj):
    return obj.number

obj = TestObj(1)


assert print_number(obj) == 1
obj.number = 2
assert print_number(obj) == 2

我希望第二个assert语句为true,因为我已经更改了对象obj的基础属性

2 个答案:

答案 0 :(得分:1)

这是可变对象的普遍问题。无论您使用哪种缓存系统,缓存的目的都是在给定相同参数的情况下再次赋予先前的值(不进行计算)。

实际上您传递了完全相同的对象(Python中is给出的真实身份),因此没有缓存系统可以猜测它的缓存是否脏了。以下是常见的解决方法:

  • 在修改对象后立即将其从缓存中弹出。这意味着number必须是一个属性,并且TestObj必须知道缓存。恕我直言,这不是很简单
  • 不缓存print_number,而是使其成为另一个函数的包装,该函数调用相关的非可变TestObj成员。小事在这里

你会

def print_number(obj):
    return do_print_number(obj.number)


@lru_cache(1024)
def do_print_number(number):
    return number

只要obj.number是一个不可更改的对象(如数字,字符串或元组,并且既不是列表,集合也不是映射),它将可以使用。

答案 1 :(得分:0)

您的示例几乎违背了lru_cache的目的。无论如何,我能想到的唯一方法是在第二个断言之前添加print_number.cache_clear()

assert print_number(obj) == 1
obj.number = 2
print_number.cache_clear()
assert print_number(obj) == 2