如何清除 memoize 缓存?

How can the memoize cache be cleared?

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

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 装饰,所以从一个测试到另一个测试,它的 return 值被缓存并且不会随着后续 [=14] 改变=]作业。

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

装饰器通过在函数中注入字典来工作

您可以手动清除该词典:

@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': {}}

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

因为距离这个被接受的答案已经过去了将近 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

所以为了 clear/delete memoize 现在我们需要使用 method1.delete_memoized.