(Un)具有Instance方法对象的Pickle类

时间:2012-08-06 15:14:00

标签: python pickle

我有一个类(Bar),它有效地拥有自己的状态和回调,并被另一个类(Foo)使用:

 class Foo(object):

     def __init__(self):
         self._bar = Bar(self.say, 10)
         self._bar.work()

     def say(self, msg):
         print msg

 class Bar(object):
     def __init__(self, callback, value):
         self._callback = callback
         self._value = value
         self._more = { 'foo' : 1, 'bar': 3, 'baz': 'fubar'}

     def work(self):
         # Do some work
         self._more['foo'] = 5
         self._value = 10
         self._callback('FooBarBaz')

 Foo()

显然我不能挑选课程Foo因为Bar有一个实例方法,所以我留下了以下实施__getstate__&的解决方案。 __setstate__ Bar self._value保存self._more& self._callback,但我必须实例化__init__()方法(即通过回调函数从外部类Foo调用{{1}}。

但我无法弄清楚如何实现这一点。

非常感谢任何帮助 感谢。

1 个答案:

答案 0 :(得分:1)

我认为如果您需要序列化这样的东西,您需要能够将回调定义为字符串。例如,您可能会说callback = 'myproject.callbacks.foo_callback'

基本上在__getstate__中,您可以将_callback函数替换为可用于稍后查找函数的内容,例如self._callback.__name__

__setstate__中,您可以使用函数替换_callback

这取决于你的所有函数都有真实名称所以你不能使用lambda作为回调并期望它被序列化。您还需要一个合理的机制来按名称查找您的功能。

您可以使用__import__(类似于:'myproject.somemodule.somefunc'点名称语法可以支持这种方式,请参阅http://code.google.com/p/mock/source/browse/mock.py#1076)或只在代码中定义查找表。< / p>

快速(未经测试,抱歉!)示例假设您在查找表中定义了一小组可能的回调:

def a():
    pass

callbacks_to_name = {a: 'a'
                     # ...
                     }

callbacks_by_name = {'a': a,
             # ...
             }

class C:
    def __init__(self, cb):
        self._callback = cb

    def __getstate__(self):
        self._callback = callbacks_to_name[self._callback]
        return self.__dict__

    def __setstate__(self, state):
        state[_callback] = callbacks_by_name[self._callback]

我不确定您的用例是什么,但我建议您通过将工作项序列化为JSON或XML并编写一组简单的函数来自行序列化和反序列化。

好处是人类可以读取和理解序列化格式,并在升级软件时进行修改。 Pickle很有诱惑力,因为它似乎足够接近,但是当你有一堆__getstate____setstate__时,你还没有真正为自己的应用程序专门为自己的应用程序而努力或头疼