Skip to content

Instantly share code, notes, and snippets.

@robinhouston
Created October 13, 2010 22:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robinhouston/625130 to your computer and use it in GitHub Desktop.
Save robinhouston/625130 to your computer and use it in GitHub Desktop.
class lazy(object):
'''A simple lazy evaluation hack, with just enough magic to be
useful for passing as a value to a Django template.
Creates a lazy wrapper around a function call, when used as
lazy(function, argument_1, argument_2, ...)
The resulting object is callable, and calling it (with no arguments) will
evaluate the function on the arguments passed to the constructor.
Trying to access the object in other ways (getting attributes, getting items,
iterating over it) will evaluate the function, if it hasn't already been evaluated,
and then delegate to the result.
The net effect is that the resulting "lazy" object can be used in a Django
template just as if it were the actual result of the function call, except
that the function will not be evaluated unless and until it is in fact so used.
'''
def __init__(self, f, *args, **kwargs):
self.__f, self.__args, self.__kwargs, self.__computed = f, args, kwargs, False
def __call__(self):
if not self.__computed:
self.__computed, self.__value = True, self.__f(*self.__args, **self.__kwargs)
return self.__value
def __getattribute__(self, name):
if name.startswith("_lazy__"):
return super(lazy, self).__getattribute__(name)
return getattr(self(), name)
def __iter__(self):
return iter(self())
def __str__(self):
return str(self())
def __nonzero__(self):
return bool(self())
def __len__(self):
return len(self())
def __getitem__(self, item):
return self().__getitem__(item)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment