How to memoize **kwargs?

前端 未结 5 1192
情深已故
情深已故 2020-12-28 17:51

I haven\'t seen an established way to memoize a function that takes key-word arguments, i.e. something of type

def f(*args, **kwargs)

since

5条回答
  •  佛祖请我去吃肉
    2020-12-28 18:24

    Here:

    from functools import wraps
    
    def memoize(fun):
        """A simple memoize decorator for functions supporting positional args."""
        @wraps(fun)
        def wrapper(*args, **kwargs):
            key = (args, frozenset(sorted(kwargs.items())))
            try:
                return cache[key]
            except KeyError:
                ret = cache[key] = fun(*args, **kwargs)
            return ret
        cache = {}
        return wrapper
    

    Tests:

    import unittest
    
    class TestMemoize(unittest.TestCase):
        def test_it(self):
            @memoize
            def foo(*args, **kwargs):
                "foo docstring"
                calls.append(None)
                return (args, kwargs)
    
            calls = []
            # no args
            for x in range(2):
                ret = foo()
                expected = ((), {})
                self.assertEqual(ret, expected)
                self.assertEqual(len(calls), 1)
            # with args
            for x in range(2):
                ret = foo(1)
                expected = ((1, ), {})
                self.assertEqual(ret, expected)
                self.assertEqual(len(calls), 2)
            # with args + kwargs
            for x in range(2):
                ret = foo(1, bar=2)
                expected = ((1, ), {'bar': 2})
                self.assertEqual(ret, expected)
                self.assertEqual(len(calls), 3)
            self.assertEqual(foo.__doc__, "foo docstring")
    
    unittest.main()
    

    This works as long as you don't pass an unhashable type (e.g. dict) as argument. I don't have a solution for that but collections.lru_cache() implementation might have. See _make_key() function here: http://code.activestate.com/recipes/578078/

提交回复
热议问题