How does Lru_cache (from functools) Work?

前端 未结 3 516
自闭症患者
自闭症患者 2020-12-12 22:33

Especially when using recursive code there are massive improvements with lru_cache. I do understand that a cache is a space that stores d

3条回答
  •  难免孤独
    2020-12-12 23:23

    The functools source code is available here: https://github.com/python/cpython/blob/3.6/Lib/functools.py

    lru_cache uses the _lru_cache_wrapper decorator (python decorator with arguments pattern) which has a cache dictionary in context in which it saves the return value of the function called (every decorated function will have its own cache dict). The dictionary key is generated with the _make_key function from the arguments. Added some bold comments below:

    # ACCORDING TO PASSED maxsize ARGUMENT _lru_cache_wrapper
    # DEFINES AND RETURNS ONE OF wrapper DECORATORS
    
    def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):
        # Constants shared by all lru cache instances:
        sentinel = object()      # unique object used to signal cache misses
    
        cache = {}                                # RESULTS SAVES HERE
        cache_get = cache.get    # bound method to lookup a key or return None
    
        # ... maxsize is None:
    
        def wrapper(*args, **kwds):
            # Simple caching without ordering or size limit
            nonlocal hits, misses
            key = make_key(args, kwds, typed)     # BUILD A KEY FROM ARGUMENTS
            result = cache_get(key, sentinel)     # TRYING TO GET PREVIOUS CALLS RESULT
            if result is not sentinel:            # ALREADY CALLED WITH PASSED ARGUMENTS
                hits += 1
                return result                     # RETURN SAVED RESULT
                                                  # WITHOUT ACTUALLY CALLING FUNCTION
            result = user_function(*args, **kwds) # FUNCTION CALL - if cache[key] empty
            cache[key] = result                   # SAVE RESULT
            misses += 1
            return result
        # ...
    
        return wrapper
    

提交回复
热议问题