Memoizing decorator

Daishi Harada daishi at gmail.com
Mon Dec 5 19:15:38 EST 2005


Hi,

I'm trying to find/write a memoizing decorator
that works both for functions and methods.
I've been looking at the following two samples:

http://wiki.python.org/moin/PythonDecoratorLibrary#head-11870a08b0fa59a8622201abfac735ea47ffade5
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/325205

AFAICT, both of these seem to be targetting bare
functions (the second seems to break with:
    unbound methods must have non-NULL im_class
).

I'm using the following code to test the decorators:

---
def test_memoize(memoize_fn):
    @memoize_fn
    def fn(x):
        print '(eval %s)' % str(x),
        return x
    print 'fn', fn(1)
    print 'fn', fn(1)

    class A(object):
        @memoize_fn
        def fn(self, x):
            print '(eval %s)' % str(x),
            return x
    a = A()
    print 'meth', a.fn(1)
    print 'meth', a.fn(1)
---

In the method test, I get:
    fn() takes exactly 2 arguments (1 given)

As I understand things the difficulty here
is due to the way Python resolves between
functions, unbound methods, and bound
methods, which I have a basic sense of,
and how user-defined callables fits into
this picture, which I'm not very clear on.
I *think* the reason this exception comes
up is because user-defined callables don't
automagically get a 'self' prepended to
the argument list.

So I've managed to get these working for both
functions and methods by wrapping them in
yet another function (the following is for the
cookbook example, replacing 'cachedmethod'):

---
def memoize(function):
    im = Memoize(function)
    def fn(*args, **kwargs):
        return im(*args, **kwargs)
    return fn
---

However, this seems wasteful in that there
are now 2 "wrapper" function invocations
before one gets to the underlying function.

I would appreciate any advice on how to
proceed/clean this up.

Thanks,
Daishi




More information about the Python-list mailing list