memoize IntType constructor
[p2pool.git] / p2pool / util / memoize.py
1 import itertools
2
3 class LRUDict(object):
4     def __init__(self, n):
5         self.n = n
6         self.inner = {}
7         self.counter = itertools.count()
8     def get(self, key, default=None):
9         if key in self.inner:
10             x, value = self.inner[key]
11             self.inner[key] = self.counter.next(), value
12             return value
13         return default
14     def __setitem__(self, key, value):
15         self.inner[key] = self.counter.next(), value
16         while len(self.inner) > self.n:
17             self.inner.pop(min(self.inner, key=lambda k: self.inner[k][0]))
18
19 _nothing = object()
20
21 def memoize_with_backing(backing, has_inverses=set()):
22     def a(f):
23         def b(*args):
24             res = backing.get((f, args), _nothing)
25             if res is not _nothing:
26                 return res
27             
28             res = f(*args)
29             
30             backing[(f, args)] = res
31             for inverse in has_inverses:
32                 backing[(inverse, args[:-1] + (res,))] = args[-1]
33             
34             return res
35         return b
36     return a
37
38 def memoize(f):
39     return memoize_with_backing({})(f)
40
41
42 class cdict(dict):
43     def __init__(self, func):
44         dict.__init__(self)
45         self._func = func
46     
47     def __missing__(self, key):
48         value = self._func(key)
49         self[key] = value
50         return value
51
52 def fast_memoize_single_arg(func):
53     return cdict(func).__getitem__
54
55 class cdict2(dict):
56     def __init__(self, func):
57         dict.__init__(self)
58         self._func = func
59     
60     def __missing__(self, key):
61         value = self._func(*key)
62         self[key] = value
63         return value
64
65 def fast_memoize_multiple_args(func):
66     f = cdict2(func).__getitem__
67     return lambda *args: f(args)