如何清除memoize缓存?

时间:2015-04-28 11:43:06

标签: python unit-testing caching

我使用以下装饰器来缓存纯函数返回:

def memoize(obj):
    cache = obj.cache = {}

    @functools.wraps(obj)
    def memoizer(*args, **kwargs):
        if args not in cache:
            cache[args] = obj(*args, **kwargs)
        return cache[args]
    return memoizer

它工作得很好,但我遇到了单元测试的问题,例如:

class TestFoo(unittest.TestCase):

    def setUp(self):
        # clear the cache here
        pass

    @patch('module1.method1')
    def test_method1_1(self, method1):
        method1.return_value = ""
        d = module1.method2()
        self.assertTrue(len(d) == 0)

    @patch('module1.method1')
    def test_method1_2(self, method1):
        method1.return_value = "TEST1234"
        d = module1.method2()
        self.assertTrue(len(d) == 2)

我的问题是module1.method1memoize修饰,因此从一个测试到另一个测试,其返回值将被缓存,并且不会随后的method1.return_value = "..."分配而更改。

如何清除memoize缓存?当我想到这一点时,我会清除测试用例的setUp方法中的缓存。

2 个答案:

答案 0 :(得分:4)

装饰器通过在函数

中注入一个字典来工作

您可以手动清除该词典:

@memoize
def square (x):
  return x*x

square(2)
square(3)

print square.__dict__
# {'cache': {(2,): 4, (3,): 9}}

square.cache.clear()
print square.__dict__
# {'cache': {}}

您可以在TearUp方法中使用module1.method1.cache.clear()

答案 1 :(得分:1)

因为从这个公认的答案过去了将近 6 年。对于 python 3.6,这现在几乎没有什么不同:

In [26]: @memoize()
    ...: def save_random(x):
    ...:     return x * random.random()
    ...: 

In [27]: save_random(2)
Out[27]: 0.39443014715316504

In [28]: save_random(2)
Out[28]: 0.39443014715316504

In [29]: save_random(1)
Out[29]: 0.42043961241931294

In [30]: save_random(1)
Out[30]: 0.42043961241931294

In [31]: save_random.__dict__
Out[31]: 
{'__wrapped__': <function __main__.save_random(x)>,
 'uncached': <function __main__.save_random(x)>,
 'cache_timeout': <object at 0x7f0bf3f0a250>,
 'make_cache_key': <function memoize.Memoizer._memoize_make_cache_key.<locals>.make_cache_key(f, *args, **kwargs)>,
 'delete_memoized': <function memoize.Memoizer.memoize.<locals>.memoize.<locals>.<lambda>()>}

In [32]: save_random.delete_memoized()

In [33]: save_random(1)
Out[33]: 0.39032536564874865

In [34]: save_random(2)
Out[34]: 1.093048214445716

所以现在要清除/删除备忘录,我们需要使用 method1.delete_memoized