Python: 像处理基类实例一样处理派生类的Pickle

7 投票
2 回答
3291 浏览
提问于 2025-04-16 08:50

我想定义一个基础类,这样当派生类的实例被序列化时,它们就会像基础类的实例一样被序列化。这是因为派生类可能只在客户端存在,而在服务器端并不存在,但这对服务器来说并不重要,因为服务器只需要基础类的信息。我不想为每个客户端动态创建类。

这个基础类其实就是一个“对象句柄”,里面包含一个ID,方法是在服务器上定义的。不过,我希望客户端能够从服务器的类中继承,并定义新的方法(这些方法只会被客户端看到,但这并不重要)。

2 个回答

1

在Python中,你可以动态地改变一个对象的类:

import cPickle as pickle

class Foo(object):
    def __init__(self):
        self.id=1
class Bar(Foo):
    def derived_class_method(self): pass

bar=Bar()
bar.id=2
bar.__class__=Foo                # changes `bar`'s class to Foo
bar_pickled=pickle.dumps(bar)
bar2=pickle.loads(bar_pickled)
bar.__class__=Bar                # reset `bar`'s class to Bar
print(repr(bar2))
# <__main__.Foo object at 0xb76b08ec>
print(bar2.id)
# 2

不过,我不太确定这样做是否是最好的设计选择。我更喜欢Thomas K的想法,使用JSON。

2

我觉得你可以通过给这个对象添加一个 __reduce__ 方法来实现。这个方法需要返回一个元组,元组的第一个部分应该是 BaseClass.__new__(这个方法在反序列化对象时会被调用)。想了解更多细节,可以查看 pickle 的文档(Python 2Python 3)。不过我自己还没有尝试过。

根据你的具体需求,使用像 JSON 这样的简单序列化格式可能会更容易,然后在两边写代码来重建相关的对象。

撰写回答