有没有办法使用标准库在Python中序列化词法闭包?pickle和marshal似乎不适用于词法闭包。我真的不关心二进制与字符串序列化的细节,等等,它只需要工作即可。例如:
def foo(bar, baz) :
def closure(waldo) :
return baz * waldo
return closure
我希望能够将闭包实例转储到一个文件中,然后重新读取它们。
编辑:可以解决这个问题的一种相对明显的方法是使用一些反射hack将词法闭包转换为类对象,反之亦然。然后可以转换为类、序列化、反序列化、转换回闭包。如果你重载了类的函数调用操作符,使它看起来像一个函数,你甚至不需要把它转换回闭包,使用它的代码也不会知道区别。如果有任何Python反射API专家,请畅所欲言。
发布于 2009-02-22 11:42:05
如果您只是简单地使用一个带有__call__
方法的类,那么它应该能够顺利地与pickle
一起工作。
class foo(object):
def __init__(self, bar, baz):
self.baz = baz
def __call__(self,waldo):
return self.baz * waldo
另一方面,由于pickle
处理类和实例的方式,将闭包转换为在运行时创建的新类的实例的黑客将无法工作。pickle
不存储类;只存储模块名和类名。当读回一个实例或类时,它会尝试导入模块并在其中找到所需的类。如果您使用的是动态创建的类,那么您就不走运了。
发布于 2010-11-08 22:46:47
PiCloud已经发布了一个开源的pickler,它可以处理函数闭包和更多有用的东西。它可以独立于他们的云计算基础设施使用--它只是一个普通的pickler。整个过程都是文档化的安装,你可以通过'pip here‘下载代码。不管怎么说,它能做你想要的。让我们通过酸洗闭包来演示这一点:
import pickle
from StringIO import StringIO
import cloud
# generate a closure
def foo(bar, baz):
def closure(waldo):
return baz * waldo
return closure
closey = foo(3, 5)
# use the picloud pickler to pickle to a string
f = StringIO()
pickler = cloud.serialization.cloudpickle.CloudPickler(f)
pickler.dump(closey)
#rewind the virtual file and reload
f.seek(0)
closey2 = pickle.load(f)
现在我们有了closey
和closey2
,前者是原始闭包,后者是从字符串序列化中恢复的闭包。让我们来测试一下。
>>> closey(4)
20
>>> closey2(4)
20
漂亮的。这个模块是纯python的--你可以打开它,很容易地看到是什么让它变得神奇。(答案是大量的代码。)
发布于 2009-02-24 23:38:42
Recipe 500261: Named Tuples包含一个动态定义类的函数。而且这个类支持酸洗。
这是它的本质:
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
结合@Greg Ball's suggestion在运行时创建一个新类,它可能会回答您的问题。
https://stackoverflow.com/questions/573569
复制相似问题