用Python记忆整个块

时间:2021-10-01 01:05:03

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?

我想要记住上面的整个块,而不必明确关于块中创建/更改的每个变量或手动pickle它们。我怎么能用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.

理想情况下,我希望能够用某些东西(如果/ else或with语句)包装它,并有一个标志,如果我想要强制刷新。

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)

有没有办法做到这一点,而不必明确挑选代码中定义或更改的每个变量? (即在我们保存的第一次运行结束时,我们稍后只重用这些值)

2 个解决方案

#1


1  

How about using locals() to get a list of the local variables, storing them in a dict in pickle, then using (below is more conceptual):

如何使用locals()获取局部变量列表,将它们存储在pickle中的dict中,然后使用(下面更概念化):

for k,v in vars_from_pickle:
  run_string = '%s=%s' % (k,v)
  exec(run_string)

to restore your local stack. Maybe its better to use a list instead of a dict to preserve stack ordering.

恢复本地堆栈。也许最好使用列表而不是dict来保留堆栈顺序。

#2


1  

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:

有很多方法可以解决这个问题,但我认为最接近你所描述的方法是使用pythons模块作用域作为memoized,并根据需要重新加载或重新加载。像这样的东西:

# 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:

# 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

#1


1  

How about using locals() to get a list of the local variables, storing them in a dict in pickle, then using (below is more conceptual):

如何使用locals()获取局部变量列表,将它们存储在pickle中的dict中,然后使用(下面更概念化):

for k,v in vars_from_pickle:
  run_string = '%s=%s' % (k,v)
  exec(run_string)

to restore your local stack. Maybe its better to use a list instead of a dict to preserve stack ordering.

恢复本地堆栈。也许最好使用列表而不是dict来保留堆栈顺序。

#2


1  

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:

有很多方法可以解决这个问题,但我认为最接近你所描述的方法是使用pythons模块作用域作为memoized,并根据需要重新加载或重新加载。像这样的东西:

# 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:

# 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