酸洗后如何更改类方法的定义

问题描述

我正在编写一个进行一些数据处理的类。我启动了课程并进行了一些处理,然后对结果进行了腌制。 问题是我向类添加了新方法并加载了腌制对象,但我无法将新方法应用于未腌制的对象。

例如,这是我的班级

class Play(ABC):
  def __init__(self,data):
    self.data = data
    
  @abstractmethod
  def method(self):
    pass

class M(Play):

  def __init__(self,data):
    super().__init__(data)

  def method(self):
    self.corr = np.corrcoef(self.data)

我做了一些处理

mat = np.random.rand(102,641)
s = M(mat)
s.method()

然后用莳萝腌制它们

def save_object(obj,filename):
    with open(filename,'wb') as output:  
        dill.dump(obj,output,dill.HIGHEST_PROTOCOL)
save_object(s,'file.pkl')  

然后,我向类中添加了新方法并解压文件以应用这些方法,但我不能

class Play(ABC):
  def __init__(self,data):
    super().__init__(data)

  def method(self):
    self.corr = np.corrcoef(self.data)
  
  def new(self):
    # pass
    self.q = self.corr.shape
def load_object(filename):
  with open(filename,'rb') as input:
    obj = dill.load(input)
    return obj
obj = load_object('file.pkl')
obj.new()

我得到了这个结果

AttributeError: 'M' 对象没有属性 'new'

我该如何解决

解决方法

我是 dill 作者。您可能需要查看不同的酸洗设置(请参阅 dill.settings)。例如:

>>> class Foo(object):
...   x = 1
...   def bar(self,y):
...     return y + self.x
... 
>>> import dill
>>> f = Foo()
>>> s = dill.dumps(f)
>>> f.bar(5)
6
>>> 
>>> class Foo(object):
...   x = 10
...   def bar(self,y):
...     return y + self.x**2
... 
>>> g = dill.loads(s)
>>> g.bar(5)
105
>>> g = dill.loads(s,ignore=True)
>>> g.bar(5)
6
>>> dill.settings
{'protocol': 4,'byref': False,'fmode': 0,'recurse': False,'ignore': False}
>>> 

在这里,ignore=True 在加载时告诉 dill 如果存在更新的类定义,则忽略现有的类定义。其他设置将用于 dump/dumps,例如,byref=True 告诉 dill 根本不存储类定义——只需使用任何引用可在拆箱环境中使用。

,

另一种方法是使用 joblib 库。我还鼓励您查看下面参考资料部分中共享的 joblib 文档。

joblib.dump(obj,"filename.joblib")    ## Saving object to a file
obj = joblib.load("filename.joblib")   ## Loading object from a file

保存和加载您的对象:第一次

class Foo(object):
    x = 1

    def bar(self,y):
        return y + self.x

f1 = Foo()

def checkFoo(foo: Foo):
    print(f'version: {foo.version}')

## save your object
>>> version = '0.0.1'
>>> f1.version = version
>>> checkFoo(f1)
'0.0.1'
>>> joblib.dump(f1,f'object_store_v{version}.joblib')
['object_store_v0.0.1.joblib']

## load saved object (latest version)
>>> version = '0.0.1'
>>> f2 = joblib.load(f'object_store_v{version}.joblib')
>>> checkFoo(f2)
'0.0.1'

保存和加载对象:第二次(修改后

## Modify object and save new version
>>> version = '0.0.2'
>>> f2.version = version
>>> checkFoo(f2)
'0.0.2'
>>> joblib.dump(f2,f'object_store_v{version}.joblib')
['object_store_v0.0.2.joblib']

## load saved object (latest version)
>>> version = '0.0.2'
>>> f3 = joblib.load(f'object_store_v{version}.joblib')
>>> checkFoo(f3)
'0.0.2'

参考资料