在Python中排除对象字段的序列化

48 投票
4 回答
25431 浏览
提问于 2025-04-15 19:47

我想在一个类的实例中避免对某些字段进行序列化(也就是“腌制”)。现在,在序列化之前,我只是把那些字段设置为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__ 这两个方法。

撰写回答