使用
__reduce__
是一种有效的方法,正如Python文档所述:
尽管强大,但在类中直接实现
__reduce__()
存在错误的可能性。因此,类设计者应尽可能使用高级接口(即
__getnewargs_ex__()
、
__getstate__()
和
__setstate__()
)。
因此,我将解释如何使用更简单的高级接口
__getstate__
和
__setstate__
使对象可进行序列化。
假设我们有一个非常简单的类,其中包含一个无法序列化的属性,比如文件句柄。
class Foo:
def __init__(self, filename):
self.filename = filename
self.f = open(filename)
Foo
的实例不可被pickable:
obj = Foo('test.txt')
pickle.dumps(obj)
我们可以通过实现
__getstate__
和
__setstate__
使这个类可序列化和反序列化,使用pickle。
class Foo:
...
def __getstate__(self):
"""Used for serializing instances"""
state = self.__dict__.copy()
del state['f']
return state
def __setstate__(self, state):
"""Used for deserializing"""
self.__dict__.update(state)
f = open(self.filename)
self.f = f
现在它可以被腌制了:
obj = Foo('text.txt')
pickle.dumps(obj)
将这个想法应用到你问题中的例子,你可以这样做:
class MyComplicatedObject:
def __getstate__(self):
state = self.__dict__.copy()
del state['progress']
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.progress = make_progress(self.progress_int)
另一种方法是配置
pickler 以了解如何对新对象进行pickle (而不是使类/对象本身可被pickle)。例如,通过自定义的 pickler 和
dispatch_table,您可以将类注册到函数 (
__reduce__
-like) 中,以便pickle可能无法pickle的对象。
在Python 3.8+中,您还可以为对象实现 自定义reductions。
如果您试图pickle可能属于第三方库/代码的类,其中子类化(使 object 可pickle) 不切实际,则这些方法特别有用。
loads
或load
都无所谓。您的对象可以从单个int重建;您是否有一个执行此操作的函数?如果有,该函数应该是元组中的“callable”。如果您没有这样的函数,那么您可能需要编写一个。 - user2357112