Skip to content Skip to sidebar Skip to footer

Python Lazy Evaluator

Is there a Pythonic way to encapsulate a lazy function call, whereby on first use of the function f(), it calls a previously bound function g(Z) and on the successive calls f() ret

Solution 1:

I'm a bit confused whether you seek caching or lazy evaluation. For the latter, check out the module lazy.py by Alberto Bertogli.


Solution 2:

Try using this decorator:

class Memoize:
    def __init__ (self, f):
        self.f = f
        self.mem = {}
    def __call__ (self, *args, **kwargs):
        if (args, str(kwargs)) in self.mem:
            return self.mem[args, str(kwargs)]
        else:
            tmp = self.f(*args, **kwargs)
            self.mem[args, str(kwargs)] = tmp
            return tmp

(extracted from dead link: http://snippets.dzone.com/posts/show/4840 / https://web.archive.org/web/20081026130601/http://snippets.dzone.com/posts/show/4840) (Found here: Is there a decorator to simply cache function return values? by Alex Martelli)

EDIT: Here's another in form of properties (using __get__) http://code.activestate.com/recipes/363602/


Solution 3:

You can employ a cache decorator, let see an example

from functools import wraps

class FuncCache(object):
    def __init__(self):
        self.cache = {}

    def __call__(self, func):
        @wraps(func)
        def callee(*args, **kwargs):
            key = (args, str(kwargs))
            # see is there already result in cache
            if key in self.cache:
                result = self.cache.get(key)
            else:
                result = func(*args, **kwargs)
                self.cache[key] = result
            return result
        return callee

With the cache decorator, here you can write

my_cache = FuncCache()

@my_cache
def foo(n):
    """Expensive calculation

    """
    sum = 0
    for i in xrange(n):
        sum += i
    print 'called foo with result', sum
    return sum

print foo(10000)
print foo(10000)
print foo(1234)

As you can see from the output

called foo with result 49995000
49995000
49995000

The foo will be called only once. You don't have to change any line of your function foo. That's the power of decorators.


Solution 4:

There are quite a few decorators out there for memoization:

http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize http://code.activestate.com/recipes/498110-memoize-decorator-with-o1-length-limited-lru-cache/ http://code.activestate.com/recipes/496879-memoize-decorator-function-with-cache-size-limit/

Coming up with a completely general solution is harder than you might think. For instance, you need to watch out for non-hashable function arguments and you need to make sure the cache doesn't grow too large.

If you're really looking for a lazy function call (one where the function is only actually evaluated if and when the value is needed), you could probably use generators for that.

EDIT: So I guess what you want really is lazy evaluation after all. Here's a library that's probably what you're looking for:

http://pypi.python.org/pypi/lazypy/0.5


Solution 5:

Just for completness, here is a link for my lazy-evaluator decorator recipe:

https://bitbucket.org/jsbueno/metapython/src/f48d6bd388fd/lazy_decorator.py


Post a Comment for "Python Lazy Evaluator"