|
If you know before what kind of value your function call will return, you can build a very simple decorator for functions or methods that will turn them into lazy evaluation ones. It goes like this:
class NoneSoFar: pass
NoneSoFar = NoneSoFar()
def lazy(func, resultclass):
class __proxy__:
def __init__(self, args, kw):
self.__func = func
self.__args = args
self.__kw = kw
self.__result = NoneSoFar
for (k, v) in resultclass.__dict__.items():
setattr(self, k, self.__promise__(v))
def __promise__(self, func):
def __wrapper__(*args, **kw):
if self.__result is NoneSoFar:
self.__result = self.__func(*self.__args, **self.__kw)
return func(self.__result, *args, **kw)
return __wrapper__
def __wrapper__(*args, **kw):
return __proxy__(args, kw)
return __wrapper__
To use it is very simple and straight forward:
def anton(a,b):
return a+b
anton = lazy(anton, int)
print type(anton(5,6))
print str(anton(5,6))
This should print the __proxy__ instance in the first line and the real value in the second one. The proxy class automatically defines special methods for every method that's defined on the result type. This works best for builtin types, for more complex types you would have to take precautions not to stomp over important attributes.
And as you can see this won't help with ambigiously defined functions - anton could work with strings, too, but the lazy stuff will only install handlers for int magic methods.
But as the title writes: it's about simpler lazy evaluation, not the full thing 
|