import collections import functools from itertools import filterfalse from heapq import nsmallest from operator import itemgetter
class Counter(dict):
def __missing__(self, key): return 0
def lfu_cache(maxsize=100):
def decorating_function(user_function): cache = {} # mapping of args to results use_count = Counter() # times each key has been accessed kwd_mark = object() # separate positional and keyword args
# get cache entry or compute if not found try: result = cache[key] wrapper.hits += 1 except KeyError: result = user_function(*args, **kwds) cache[key] = result wrapper.misses += 1
# purge least frequently used cache entry if len(cache) > maxsize: for key, _ in nsmallest(maxsize // 10, use_count.items(), key=itemgetter(1)): del cache[key], use_count[key]