如何在向Python类添加属性时更新pickle对象
我定义了一个Python3类,然后使用pickle将实例序列化并保存到文件中。后来,我在类中添加了另一个实例属性,但我意识到,如果我加载实例并尝试引用该属性,我将得到一个“objecthasnotattribute”错误,因为实例是在没有它的情况下构建的。将新属性添加到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
# 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。