1
+ import collections
1
2
import inspect
2
3
import warnings
3
4
from functools import wraps
@@ -10,13 +11,15 @@ def decorator(func):
10
11
# type checks
11
12
if not _is_function (func ):
12
13
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' )
13
16
arg_spec = inspect .getargspec (func )
14
17
if len (arg_spec .args ) == 0 and arg_spec .varargs is None and arg_spec .keywords is None :
15
18
warnings .warn ('It\' s meaningless to do memoization on a function with no arguments' , SyntaxWarning )
16
19
17
20
# init cache for func
18
21
initial_function_id = id (func )
19
- _cache [initial_function_id ] = {}
22
+ _cache [initial_function_id ] = {} if max_items is None else collections . OrderedDict ()
20
23
21
24
@wraps (func )
22
25
def wrapper (* args , ** kwargs ):
@@ -29,6 +32,8 @@ def wrapper(*args, **kwargs):
29
32
return cache_unit ['result' ]
30
33
else : # not yet cached
31
34
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 )
32
37
specified_cache [input_args ] = {'result' : output , 'access_count' : 0 } # make cache
33
38
return output
34
39
return wrapper
@@ -65,6 +70,10 @@ def size(func=None):
65
70
return len (_cache [_retrieve_safe_function_id (func )])
66
71
67
72
73
+ def _size_explicit (func_id ):
74
+ return len (_cache [func_id ])
75
+
76
+
68
77
def _hashable_args (args , kwargs ):
69
78
kwargs_str = ''
70
79
for key , value in kwargs :
0 commit comments