Python 类的序列化设置不使用 pickle

1 投票
2 回答
814 浏览
提问于 2025-04-17 14:25

场景

我想在Python中使用面向对象的方法,这样可以把一个类的实例保存到数据文件里,并且在以后再加载回来。现在我用的方式是这样的:

class A(object):
    def __init__(self, ComplexParam1, ComplexParam2):
        self.ComplexParam1 = ComplexParam1
        self.ComplexParam2 = ComplexParam2

    @staticmethod
    def Create(EasyParam1, EasyParam2):
        #do some complex calculation to get ComplexParam1 and ComplexParam2 from EasyParam1 and EasyParam2
        return A(ComplexParam1, ComplexParam2)        

    def Save(self, Filename):
        #write ComplexParam1 and ComplexParam2 to disc

    @staticmethod
    def Load(Filename):
        #read ComplexParam1 and ComplexParam2 and call constructor
        return A(ComplexParam1, ComplexParam2)

你可以看到,ComplexParam1ComplexParam2 是需要计算的参数,创建对象 A 的时候不需要用到它们,因为获取这两个参数非常复杂。而 EasyParam1EasyParam2 是“已知”的参数。可以把 EasyParameters 想象成整数,而 ComplexParameters 则是基于 EasyParameters 构建的大矩阵。

所以我用上面的设置来 SaveLoad 对象到文件中,其中 Create 使用构造函数,因为 ComplexParam1ComplexParam2 已经存储在文件里,不需要再计算一次。

问题

到目前为止,上面的做法对我来说都很好用。但是,当这个方案用于类的继承时,就出现了问题。所以我在寻找一个更好、更简洁的解决方案。

在C++中,我可以重载构造函数,提供两种创建类的方式,但在Python中不支持这样做。

任何帮助、链接或建议都非常感谢。

2 个回答

0

其实不需要重载,只要用一个叫 classmethod 的东西来创建不同的构造方法就可以了。你可以看看这个问题和它的回答。

class A (object):

    @classmethod
    def Load(cls, Filename):
        #read ComplexParam1 and ComplexParam2 and call constructor
        return cls(ComplexParam1, ComplexParam2)

使用这个类的参数 cls,可以很好地支持继承。

1

我觉得这是使用 @classmethod 装饰器的一个好例子。比如,如果你把 Load 方法改成下面这样:

    @classmethod
    def Load(cls, Filename):
        # Do stuff
        return cls(ComplexA, ComplexB)

那么你就可以重写构造函数了:

class B(A):
    def __init__(self, complexA, complexB):
        # Whatever you want, including calling the parent constructor

最后,你可以调用 B.Load(some_file),这会触发 B.__init__ 方法。

撰写回答