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
Post a Comment