Memoizing an entire block in Python
Question: Say I have some code that creates several variables:

    
    
    # Some code
    
    # Beginning of the block to memoize
    a = foo()
    b = bar()
    ...
    c =
    # End of the block to memoize
    
    # ... some more code
    

I would like to **memoize** the entire block above without having to be
explicit about every variable created/changed in the block or pickle them
manually. How can I do this in Python?

Ideally I would like to be able to wrap it with something (`if/else` or `with`
statement) and have a flag that forces a refresh if I want.

**Conceptually** speaking, it woul dbe like:

    
    
    # Some code
    
    # Flag that I can set from outside to save or force a reset of the chache 
    refresh_cache = True
    
    if refresh_cache == False
       load_cache_of_block()
    else:      
       # Beginning of the block to memoize
       a = foo()
       b = bar()
       ...
       c = stuff()
       # End of the block to memoize
    
       save_cache_of_block()
    
    # ... some more code
    

Is there any way to do this without having to explicitly pickle each variable
defined or changed in the code? (i.e. at the end of the first run we save, and
we later just reuse the values)


Answer: There are a lot of ways to go about this but I think the way that's closest to
what you're describing would be to use pythons `module scope` as your memoized
and `import` or `reload` as needed. Something like this:

    
    
    # a.py
    import b
    
    print b.a, b.b
    b.func(5)
    b.b = 'world'
    print b.a, b.b
    
    if b.needs_refresh():
        reload(b)
    
    print b.a, b.b
    

With your "variable scope" being the module `b`:

    
    
    # b.py
    a = 0
    b = 'hello'
    
    def func(i):
        global a
        a += i
    
    def needs_refresh():
        return a >= 5
    

Executing this results in what you'd expect:

    
    
     0 hello
     5 world
     0 hello
    

Edit: to be allow you to copy and save the entire scope you could just use a
class scope:

    
    
     memo_stack = list()
    
     class MemoScope(object):
         def __init__(self):
             self.a = 0
             self.b = 'hello'
    
     memo = MemoScope()
     memo.a = 2
     memo.b = 3
    
     memo_stack.append(memo)
     memo_stack.append(MemoScope())
    
     for i, o in enumerate(memo_stack):
         print "memo t%i.a = %s" % (i, o.a)
         print "memo t%i.b = %s" % (i, o.b)
         if o.a == 2:
             memo_stack[i] = MemoScope()
             print "refreshed"
    
    # memo t0.a = 2
    # memo t0.b = 3
    # refreshed
    # memo t1.a = 0
    # memo t1.b = hello
    

