【问题标题】:How can the memoize cache be cleared?memoize缓存如何清除?
【发布时间】:2015-04-28 11:43:05
【问题描述】:

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

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 方法中清除缓存。

【问题讨论】:

    标签: python unit-testing caching


    【解决方案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
    

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

    【讨论】:

      【解决方案2】:

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

      您可以手动清除该词典:

      @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()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-07
        • 2012-11-12
        • 2011-05-10
        • 2011-11-04
        • 2017-02-11
        • 2020-03-13
        • 2013-02-09
        • 2011-10-17
        相关资源
        最近更新 更多