Skip to main content
 首页 » 编程设计

python之(Un)Pickle 类具有 Instancemethod 对象

2025年05月04日9rubylouvre

我有一个类 (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() 

显然我不能 pickle 类 Foo 因为 Bar 有一个实例方法,所以我剩下以下实现 __getstate__ 的解决方案> & __setstate__ 在 Bar 中保存 self._value & self._more,但我必须实例化 self._callback 方法(即从外部类 Foo 调用 __init__() 传递回调函数。

但我不知道如何实现这一目标。

非常感谢任何帮助。
谢谢。

请您参考如下方法:

我认为如果你需要序列化这样的东西,你需要能够将你的回调定义为一个字符串。例如,您可以说 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 )或只在您的代码中定义一个查找表。

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

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__ 时,你并没有真正为自己节省很多精力或头痛来构建你的专为您的应用而设计的方案。