1+ import collections
12import inspect
23import warnings
34from functools import wraps
@@ -10,13 +11,15 @@ def decorator(func):
1011 # type checks
1112 if not _is_function (func ):
1213 raise TypeError ('Unable to do memoization on non-function object ' + str (func ))
14+ if max_items is not None and (not isinstance (max_items , int ) or max_items <= 0 ):
15+ raise ValueError ('Illegal max_items <' + str (max_items ) + '>: must be a positive integer' )
1316 arg_spec = inspect .getargspec (func )
1417 if len (arg_spec .args ) == 0 and arg_spec .varargs is None and arg_spec .keywords is None :
1518 warnings .warn ('It\' s meaningless to do memoization on a function with no arguments' , SyntaxWarning )
1619
1720 # init cache for func
1821 initial_function_id = id (func )
19- _cache [initial_function_id ] = {}
22+ _cache [initial_function_id ] = {} if max_items is None else collections . OrderedDict ()
2023
2124 @wraps (func )
2225 def wrapper (* args , ** kwargs ):
@@ -29,6 +32,8 @@ def wrapper(*args, **kwargs):
2932 return cache_unit ['result' ]
3033 else : # not yet cached
3134 output = func (* args , ** kwargs ) # execute func
35+ if max_items is not None and _size_explicit (function_id ) >= max_items :
36+ specified_cache .popitem (last = False )
3237 specified_cache [input_args ] = {'result' : output , 'access_count' : 0 } # make cache
3338 return output
3439 return wrapper
@@ -65,6 +70,10 @@ def size(func=None):
6570 return len (_cache [_retrieve_safe_function_id (func )])
6671
6772
73+ def _size_explicit (func_id ):
74+ return len (_cache [func_id ])
75+
76+
6877def _hashable_args (args , kwargs ):
6978 kwargs_str = ''
7079 for key , value in kwargs :
0 commit comments