Hi Bengt, Thanks for your reply.
>First, I would suggest thinking about the exact semantics of method >memoization. E.g. suppose you write > > class Oops(object): > def __init__(self, factor): self.factor = factor > @memoize_fn > def mul(self, x): > return self.factor * x > >You would need a separate cache for every instance to use x as a cache lookup >key, >or look up with say (x, id(self)), either way assuming that self.factor can't >change. You're right; I wasn't thinking clearly enough. I was in fact hoping to get the same memoize to work with classmethods also. I wonder if you wouldn't mind taking a look at the following - it seems to "work" as given, but I'm likely missing something again. In particular, if one flips the order of the 'classmethod' and 'memoize_fn' decorators, I get a 'classmethod not callable' error, and I'm losing track of what's really going on. (I've also "pushed" all of your logic into a single descriptor class - am I forgetting something by doing so?) Thanks again and in advance for your response, Daishi --- def test_memoize(memoize_fn): def printsep(): print '-'*30 @memoize_fn def fn(x): print '(eval %s)' % str(x), return x print 'fn', fn(1); printsep() print 'fn', fn(1); printsep() class A(object): n_insts = 0 def __init__(self, n): self.n = n A.n_insts += 1 @memoize_fn def fn(self, x): print '(eval %s %s)' % (str(self), str(x)) return x+self.n # The following will memoize the wrong answer # unless all instances are created first. @classmethod @memoize_fn def clsfn(cls, x): print '(clsmeth %s %s)' % (str(cls), str(x)) return x+cls.n_insts def test_class(a): print 'meth', a.fn(1); printsep() print 'meth', a.fn(1); printsep() print 'clsmeth', A.clsfn(1); printsep() print 'clsmeth', A.clsfn(1); printsep() a1 = A(1) a2 = A(2) test_class(a1) test_class(a2) class DescriptorMemoize(object): def __init__(self, fn): self.fn = fn self._cache = {} self._inst = None def __get__(self, inst, owner): print '__get__', inst, owner self._inst = inst return self def __call__(self, *args): if self._inst is not None: args = (self._inst,)+args try: return self._cache[args] except KeyError: value = self.fn(*args) self._cache[args] = value return value except TypeError: return self.fn(*args) -- http://mail.python.org/mailman/listinfo/python-list