# Lazy evaluation function decorator

Suppose I have some expensive function expensive_computation which takes a long time to compute but it always returns the same value.

I want to avoid paying the cost of computing this function because it may never be called.

Here is my solution to this, is there a more obvious or clean way to do it? Or maybe even some function from the standard library?

def lazy(function):

internal_state = None

def lazy_evaluation():
nonlocal internal_state
if internal_state is None:
internal_state = function()
return internal_state

return lazy_evaluation

@lazy
def expensive_computation():
print("Working ...")
return "that was hard"

print(expensive_computation())
print(expensive_computation())


Which prints:

Working ...
that was hard
that was hard

• Suppose this isn't real code, then it's undeniably off-topic here. Is only lazy up for review, and do you want any and all facets of your code reviewed? Please ensure your question is otherwise on-topic. – Peilonrayz May 3 at 16:31
• Any review concerning the implementation of lazy or the use of such a construct is what I'm looking for. I'm not sure what you mean by "real code", it's some working code, where I replaced every piece on which I don't want advice on by dummy code (I don't need advice on the content of expensive_computation, that's why I don't provide its implementation). On the other hand, the implementation of lazy is the exact one I intend to use. I added the output to make clear what behaviour I expect (because I noticed the term "lazy evaluation" is actually broader than this use case). – cglacet May 3 at 16:42
• Please see What to do when someone answers. I have rolled back Rev 2 → 1. – 200_success May 3 at 17:34

    if internal_state is None:
internal_state = function()


What if function() returns None?

Or maybe even some function from the standard library?

functools.lru_cache

• So how do you change the code with regard to the first point if None is a valid return? – Peilonrayz May 3 at 16:48
• My function never return None, but in the general case I guess that you would just have a boolean marker beside the internal_state, so you can tell if the function has been evaluated or not, but that's just a guess and probably not the best solution either. Concerning the cache solution I'll have a look at it. – cglacet May 3 at 17:09
• @Peilonrayz, the obvious approach would be to use a separate Boolean variable. An alternative, which I consider hackier, would be to not have a separate variable for internal_state at all: result = function(); function = lambda () => result; return result – Peter Taylor May 3 at 17:18