Using @functools.lru_cache with dictionary arguments

前端 未结 6 2038
栀梦
栀梦 2020-12-24 12:16

I have a method that takes (among others) a dictionary as an argument. The method is parsing strings and the dictionary provides replacements for some substrings, so it does

6条回答
  •  清歌不尽
    2020-12-24 13:01

    Instead of using a custom hashable dictionary, use this and avoid reinventing the wheel! It's a frozen dictionary that's all hashable.

    https://pypi.org/project/frozendict/

    Code:

    def freezeargs(func):
        """Transform mutable dictionnary
        Into immutable
        Useful to be compatible with cache
        """
    
        @functools.wraps(func)
        def wrapped(*args, **kwargs):
            args = tuple([frozendict(arg) if isinstance(arg, dict) else arg for arg in args])
            kwargs = {k: frozendict(v) if isinstance(v, dict) else v for k, v in kwargs.items()}
            return func(*args, **kwargs)
        return wrapped
    

    and then

    @freezeargs
    @lru_cache
    def func(...):
        pass
    

    Code taken from @fast_cen 's answer

    Note: this does not work on recursive datastructures; for example, you might have an argument that's a list, which is unhashable. You are invited to make the wrapping recursive, such that it goes deep into the data structure and makes every dict frozen and every list tuple.

    (I know that OP nolonger wants a solution, but I came here looking for the same solution, so leaving this for future generations)

提交回复
热议问题