caching - Function which computes once, caches the result, and returns from cache infinitely (Python) -


i have function performs expensive operation , called often; but, operation needs performed once - result cached.

i tried making infinite generator didn't results expected:

>>> def g(): ...     result = "foo" ...     while true: ...         yield result ...  >>> g() <generator object g @ 0x1093db230>    # why didn't give me "foo"? 

why isn't g generator?

>>> g <function g @ 0x1093de488> 

edit: it's fine if approach doesn't work, need performs regular function, so:

>>> [g() x in range(3)] ["foo", "foo", "foo"] 

here's dead-simple caching decorator. doesn't take account variations in parameters, returns same result after first call. there fancier ones out there cache result each combination of inputs ("memoization").

import functools  def callonce(func):      result = []      @functools.wraps(func)     def wrapper(*args, **kwargs):         if not result:             result.append(func(*args, **kwargs))         return result[0]      return wrapper 

usage:

@callonce def long_running_function(x, y, z):     # expensive x, y, , z, producing result     return result 

if prefer write function generator reason (perhaps result different on each call, there's still time-consuming initial setup, or else want c-style static variables allow function remember bit of state 1 call next), can use decorator:

import functools  def gen2func(generator):      gen = []      @functools.wraps(generator)     def wrapper(*args, **kwargs):         if not gen:             gen.append(generator(*args, **kwargs))         return next(gen[0])      return wrapper 

usage:

@gen2func def long_running_function_in_generator_form(x, y, z):     # expensive x, y, , z, producing result     while true:          yield result         result += 1    # example 

a python 2.5 or later version uses .send() allow parameters passed each iteration of generator follows (note **kwargs not supported):

import functools  def gen2func(generator):      gen = []      @functools.wraps(generator)     def wrapper(*args):         if not gen:             gen.append(generator(*args))             return next(gen[0])         return gen[0].send(args)      return wrapper  @gen2func def function_with_static_vars(a, b, c):     # time-consuming initial setup goes here     # initialize "static" vars here     while true:         # a, b, c         a, b, c = yield        # next a, b, c 

Comments

Popular posts from this blog

c++ - Creating new partition disk winapi -

Android Prevent Bluetooth Pairing Dialog -

VBA function to include CDATA -