在Python中排除对象字段的序列化
我想在一个类的实例中避免对某些字段进行序列化(也就是“腌制”)。现在,在序列化之前,我只是把那些字段设置为None,但我在想有没有更优雅的解决办法?
4 个回答
27
序列化(Pickling)会使用对象的 __getstate__
和 __setstate__
方法;你可以重写这两个方法,选择忽略你不想保存的字段。
# foo.py
class Foo:
def __init__(self):
self.bar = 1
self.baz = 2
def __getstate__(self):
state = self.__dict__.copy()
# Don't pickle baz
del state["baz"]
return state
def __setstate__(self, state):
self.__dict__.update(state)
# Add baz back since it doesn't exist in the pickle
self.baz = 0
# main.py
import pickle
from foo import Foo
foo = Foo()
print(f"Foo bar: {foo.bar} baz: {foo.baz}")
new_foo = pickle.loads(pickle.dumps(foo))
print(f"New bar: {new_foo.bar} baz: {new_foo.baz}")
输出结果:
Foo bar: 1 baz: 2
New bar: 1 baz: 0
你可以在这里找到另一个例子: https://docs.python.org/3/library/pickle.html#handling-stateful-objects
58
处理那些不能被保存的对象属性的一种方法是使用一些特殊的方法,这些方法可以用来修改类实例的状态:__getstate__()
和 __setstate__()
。下面是一个例子。
class Foo(object):
def __init__(self, value, filename):
self.value = value
self.logfile = file(filename, 'w')
def __getstate__(self):
"""Return state values to be pickled."""
f = self.logfile
return (self.value, f.name, f.tell())
def __setstate__(self, state):
"""Restore state from the unpickled state values."""
self.value, name, position = state
f = file(name, 'w')
f.seek(position)
self.logfile = f
当一个 Foo
的实例被保存时,Python 只会保存调用这个实例的 __getstate__()
方法时返回的值。同样,在恢复这个实例的时候,Python 会把恢复后的值作为参数传给实例的 __setstate__()
方法。在 __setstate__()
方法内部,我们可以根据之前保存的名称和位置信息重新创建文件对象,并把这个文件对象赋值给实例的 logfile 属性。
参考链接: http://www.ibm.com/developerworks/library/l-pypers.html
24
文档里有一个例子,可以解决你的问题,它使用了 __getstate__
和 __setstate__
这两个方法。