如何在向Python类添加属性时更新pickle对象

如何在向Python类添加属性时更新pickle对象,python,python-3.x,pickle,Python,Python 3.x,Pickle,我定义了一个Python3类,然后使用pickle将实例序列化并保存到文件中。后来,我在类中添加了另一个实例属性,但我意识到,如果我加载实例并尝试引用该属性,我将得到一个“objecthasnotattribute”错误,因为实例是在没有它的情况下构建的。将新属性添加到pickle对象并对其进行配置的最佳选项是什么 在代码中,我定义了一个类,如 # First definition class Foo: def __init__(self, params): # define and

我定义了一个Python3类,然后使用pickle将实例序列化并保存到文件中。后来,我在类中添加了另一个实例属性,但我意识到,如果我加载实例并尝试引用该属性,我将得到一个“objecthasnotattribute”错误,因为实例是在没有它的情况下构建的。将新属性添加到pickle对象并对其进行配置的最佳选项是什么

在代码中,我定义了一个类,如

# First definition
class Foo:
  def __init__(self, params):
    # define and initialize attributes
  def print_number(self):
    print(2)
我使用pickle创建并序列化了一个实例,并将其保存到文件中

import pickle

inst = Foo(params)
with open("filename", 'wb') as f:
  pickle.dump(inst, f)
然后我希望我的类的行为有点不同,所以我更新了它的定义:

# Updated definition
class Foo:
  def __init__(self, params):
    # define and initialize attributes
    self.bar = "baz"                    # bar is a new attribute
  def print_number(self):
    print(3)                            # prints 3 instead of 2
然后我加载实例并尝试调用一些方法

import pickle

with open("filename", 'rb') as f:
  inst = pickle.load(f)

inst.print_number()
print(inst.bar)
由于pickle不保存方法定义,因此实例方法的行为将被更新,以便
inst.print_number()
打印
3
,而不是
2
。但是,引用
inst.bar
会导致“对象没有属性”错误,因为
inst
是在
Foo
定义该属性之前初始化的

更新

就我而言,这是一个很难回答的问题,我没有意识到Python只允许您执行类似于
inst.bar=“baz”
的操作,并动态地进行设置(我来自Java背景,从一开始就必须解决所有问题)。我仍然对如何正确地和/或具体地进行Pythonicaly和/或pickle感兴趣,尤其是当需要进行多个类更新时。

您可以使用以下方法向现有类添加新方法/属性:

# First definition
class Foo:
    def __init__(self, params):
        self.params = params
    def print_number(self):
        print(2)

import pickle

inst = Foo('params')
with open("filename", 'wb') as f:
    pickle.dump(inst, f)

del inst

# Updated definition
class Foo(Foo):
    def __init__(self, params):
        super().__init__(params)
        self.bar = "baz"                    # bar is a new attribute
    def print_number(self):
        print(3)


with open("filename", 'rb') as f:
    inst = Foo(pickle.load(f))

inst.print_number()
print(inst.bar)

# Outputs:
# 3
# baz
或者在实践中,这样做可能更有意义:

with open("filename", 'rb') as f:
    inst = pickle.load(f)

# Updated definition
class Foo(inst.__class__):
    def __init__(self, params):
        super().__init__(params)
        self.bar = "baz"                    # bar is a new attribute
    def print_number(self):
        print(3)



inst = Foo(inst)
inst.print_number()
print(inst.bar)

这是一个有趣的想法。像这样的东西是否适合进行多次更新?是的,我不明白为什么不保存
实例。\uuuu dict\uuuu
和它引用的类,然后在加载时重新创建它?(例如,
pickle.dump(inst.\u dict\u,f)
保存,
inst=Foo.\u new\u();inst.\u dict\u.update(pickle.load(f))
加载)。这样,您只保存/更新内部状态,而不实际清理实例。也就是说,保存状态后更改定义通常不是一个好主意-如果您希望这种情况定期发生,那么您应该重新考虑您的设计并自行处理保存/加载状态,而不是依赖效率低下的pickle。