使用pickle保存和加载派生类的一个实例
正如在 这个回答 中所解释,可以使用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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。