On Nov 29, 3:20 pm, "Michael Speer" <[EMAIL PROTECTED]> wrote: > I posted this to my blog > athttp://michaelspeer.blogspot.com/2007/11/context-manager-for-temporar.... > > I decided to forward it onto the list for comments. I thought someone > might find it interesting. > > *** > > This is very much a fragile hack at the moment. It's an interesting > idea I think. I was disappointed when I initially found that the > with_statement syntax does not restore the value of the `as var` upon > completion. > > This made doing something along the lines of > > with temporarily_memoized( func ) : > for datum in data : > func( datum ) > > unattainable. > > Well, just a lot hackier actually. > > Thus temporarily_memoized( ... ) was born : > > #!/usr/bin/python > > # a context manager for temporarily turning any function into > # a memoized version of itself. > > from __future__ import with_statement > import contextlib , sys , types > > def memoize ( func ) : > """ In haskell mutability must be handled explicitly. > Only fair that Python do the same to transparent functionality > """ > remembered = {} > def memoized ( *args ) : > """ memoized version of function """ > if args in remembered : > return remembered[ args ] > else : > new = func( *args ) > remembered[ args ] = new > return new > return memoized > > @contextlib.contextmanager > def temporarily_memoized ( func ) : > """ memoize the given function for the duration of this block > save anything in the local variables that gets in the way of > using this so that it can be restored afterward , the memoized > version is found in the locals. use on actual functions only. > no members. """ > > # this is being called, there has to be a frame above it > frame = sys._getframe().f_back.f_back > > if func.func_name in frame.f_locals : > f = frame.f_locals[ func.func_name ] > frame.f_locals[ func.func_name ] = memoize( func ) > try : > # this hack replaces whatever in the local scope > # has the name of the variable. if you try to use > # the 'as whatever' portion of the syntax , you > # are doing it wrong > yield None > finally : > frame.f_locals[ f.func_name ] = f > else : > frame.f_locals[ func.func_name ] = memoize( func ) > try : > yield None > finally : > del frame.f_locals[ func.func_name ] > > def fib(n): > """ biggus fibbus """ > if n == 0 or n == 1: > return n > else: > return fib(n-1) + fib(n-2) > > if __name__ == '__main__' : > print fib.__doc__ > with temporarily_memoized( fib ) : > print fib.__doc__ > for i in xrange( 36 ) : > print "n=%d => %d" % (i, fib(i)) > print fib.__doc__ > print fib.__doc__ > > outputs : > > biggus fibbus > memoized version of function > n=0 => 0 > ..... > n=35 => 9227465 > memoized version of function > biggus fibbus
Did you try to use temporarily_itemized inside a function? It might not work as you think. BTW, the name temporarily_memoized is superfluous. By definition, whatever a context manager does is temporary, so using "temporarily" in the name just adds a lot of letters and tells us nothing we didn't already know. Just call it memoized. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list