def lfu_cache(maxsize=100):
 def decorating_function(user_function):
  cache = {}
  use_count = Counter()
  kwd_mark = object()
  @functools.wraps(user_function)
  def wrapper(*args, **kwds):
   key = args
   if kwds:
    key += ((kwd_mark,) + tuple(sorted(kwds.items())))
   use_count[key] += 1
   try:
    result = cache[key]
    wrapper.hits += 1
   except KeyError:
    result = user_function(*args, **kwds)
    cache[key] = result
    wrapper.misses += 1
    if (len(cache) > maxsize):
     for (key, _) in nsmallest((maxsize // 10), use_count.iteritems(), key=itemgetter(1)):
      del cache[key], use_count[key]
   return result
  def clear():
   cache.clear()
   use_count.clear()
   wrapper.hits = wrapper.misses = 0
  wrapper.hits = wrapper.misses = 0
  wrapper.clear = clear
  return wrapper
 return decorating_function

def lfu_cache ( maxsize = 100 ) : def decorating_function ( user_function ) : cache = { } use_count = Counter ( ) kwd_mark = object ( ) @ functools . wraps ( user_function ) def wrapper ( * args , ** kwds ) : key = args if kwds : key += ( ( kwd_mark , ) + tuple ( sorted ( kwds . items ( ) ) ) ) use_count [ key ] += 1 try : result = cache [ key ] wrapper . hits += 1 except KeyError : result = user_function ( * args , ** kwds ) cache [ key ] = result wrapper . misses += 1 if ( len ( cache ) > maxsize ) : for ( key , _ ) in nsmallest ( ( maxsize // 10 ) , use_count . iteritems ( ) , key = itemgetter ( 1 ) ) : del cache [ key ] , use_count [ key ] return result def clear ( ) : cache . clear ( ) use_count . clear ( ) wrapper . hits = wrapper . misses = 0 wrapper . hits = wrapper . misses = 0 wrapper . clear = clear return wrapper return decorating_function
least-frequenty-used cache decorator .