使用pickle保存和加载派生类的一个实例

编程语言 2026-07-09

正如在 这个回答 中所解释,可以使用numpy的保存/加载操作来保存一个类的实例并再次加载。

然而,如果我对派生类执行这个操作,我会丢失对该类本身的引用,引用的却是父类。如何绕过这个问题?

最小工作示例:

import numpy as np

class SampleClass(object):
    def __init__(self, a):
        self.a = a

class SampleDerivedClass(np.ndarray):
    def __new__(cls, a, parameter):
        obj = a.view(cls)
        obj.parameter = parameter
        return obj


a=np.array([1,2,3])
x=SampleClass(a)
np.save("x",x)

xx=np.load("x.npy", allow_pickle=True)
print("Saving a class and loading:", type(xx.item()))

y=SampleDerivedClass(a,42)
y+=a
print("Derived class:", type(y),y,y.parameter)
np.save("y",y)

yy=np.load("y.npy", allow_pickle=True)
print("After saving and loading:",type(yy),yy)
# Access to `yy.parameter` would result in an error.

在这里,我希望 yy 的类型是 SampleDerivedClass,但输出是:

Saving a class and loading: <class '__main__.SampleClass'>
Derived class: <class '__main__.SampleDerivedClass'> [2 4 6] 42
After saving and loading: <class 'numpy.ndarray'> [2 4 6]

解决方案

使用 dill 可能是正确的做法。

import numpy as np

class SampleDerivedClass(np.ndarray):
    def __new__(cls, a, parameter):
        print("__new__ with class", cls)
        obj = a.view(cls)
        obj.parameter = parameter
        return obj
    def __array_finalize__(self, obj):
        print("__array_finalize__ with object ",type(obj))
        if obj is None: return
        self.parameter =  getattr(obj, 'parameter', 0)
    def __init__(self, *args, **kwargs):
        print('__init__ with class %s' % self.__class__)

a=np.array(np.random.rand(40,6))
print("Init")
y=SampleDerivedClass(a,42)
print("y: ",type(y),y.shape,y.parameter)

from dill import dump,dumps,loads
print("Dump and load")
yd=loads(dumps(y))
print("After saving and loading with dill:",type(yd),yd.shape,yd.parameter)

不过在 base 属性上我又遇到了一个问题,请参阅我的 新问题

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章