在一个模块中,我有一个类需要函数作为其参数之一:
class Foo():
def __init__(self, fun):
self.fun = fun
def call_fun(self, arg):
self.fun(arg)
在另一个模块中,我有一些函数,我最终在创建这个类的对象时作为参数传递。我通过以下方式绑定值以轻松自定义函数:
def sample_function(value):
return (lambda arg: arg.effect(value))
初始化Foo对象时,我传递的值如下:
foo = Foo(sample_function(5))
后来,我想搁置一些对象,包括Foo对象,这很快就变得不可能了(因为pickle模块返回'TypeError:无法pickle函数对象')。我完全了解pickle的序列化机制的局限性,并且我意识到为什么不可能腌制这些对象。相反,我想重新设计我的课程,或使用其他序列化方法。我如何重新设计这个以便我可以搁置Foo对象,同时保留它们的属性?
答案 0 :(得分:3)
代码的主要问题是“sample_function”中的closuse。如果没有闭包,可以使用marshal和types模块来完成,这里有一些例子:
import pickle
import marshal
import types
class Foo():
def __init__(self, fun):
self.fun = fun
def call_fun(self, arg):
self.fun(arg)
def save(self, f):
saved = self.fun
self.fun = marshal.dumps(self.fun.func_code)
pickle.dump(self, f)
self.fun = saved
@staticmethod
def load(f):
foo = pickle.load(f)
foo.fun = types.FunctionType(marshal.loads(foo.fun), globals())
return foo
def sample_function(arg):
arg.effect(4)
class Arg():
def effect(self, value):
print "ok: " + str(value)
使用此类和函数,您可以保存:
foo = Foo(sample_function)
f = open('foo', 'w')
foo.save(f)
f.close()
并加载:
f = open('foo', 'r')
foo = Foo.load(f)
f.close()
这个想法是在酸洗之前编组“有趣”(并恢复它,因此不会破坏类)并在加载时将编组代码作为函数加载。
但这不适用于闭包(因为闭包需要来自调用函数的变量)。