我使用以下装饰器来缓存纯函数返回:
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.method1
被memoize
修饰,因此从一个测试到另一个测试,其返回值将被缓存,并且不会随后的method1.return_value = "..."
分配而更改。
如何清除memoize缓存?当我想到这一点时,我会清除测试用例的setUp方法中的缓存。
答案 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
。