10.1 一切都按我的方式来!
有时候,你的对象里头会有很多指向各种服务对象的引用,这些引用你可能不想通过网络传输,或者根本无法通过网络传输:比如文件,数据库等的引用。
为了让序列化在这种情况下也能正常工作,设计者让类可以自己管理序列化。为此,使用了一些特殊的方法:__reduce__()
、__getstate__()
、__setstate__()
。这些方法允许你指定对象如何被序列化和恢复。
管理序列化的主要方法有:
-
__reduce__()
:指定对象如何被序列化。 -
__getstate__()
:返回用于序列化的对象状态。 -
__setstate__(self, state)
:从状态恢复对象。
下面我会详细讲讲它们,以及如何一起使用。
10.2 方法 __reduce__()
方法 __reduce__()
返回一个元组,指定对象如何被序列化和反序列化。元组通常包含:
- 用于恢复对象的函数或类的引用。
- 该函数或类的参数元组。
- 对象的额外状态(如果需要的话)。
例子:
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
return (self.__class__, (self.value,))
def __repr__(self):
return f"CustomClass(value={self.value})"
# 创建对象
obj = CustomClass(42)
# 对象序列化
serialized_obj = pickle.dumps(obj)
print("序列化对象:", serialized_obj)
# 对象反序列化
deserialized_obj = pickle.loads(serialized_obj)
print("反序列化对象:", deserialized_obj)
默认情况下函数 __reduce__()
有如下行为:
class CustomClass:
def __init__(self, value):
self.value = value
def __reduce__(self):
# 类的定义
cls = self.__class__
# 构造函数的参数
args = (self.value,)
# 对象的状态
state = self.__dict__
return (cls, args, state)
它返回一个由三个对象组成的元组:
当前类的引用
构造函数的参数(元组)
当前对象状态的引用
如果你满意这种默认行为,那就不需要重写 __reduce__()
。
10.3 读取和写入状态
方法 __getstate__()
和 __setstate__()
这些方法用于在序列化和反序列化期间管理对象的状态。
-
__getstate__()
:返回应该被序列化的对象状态。 -
__setstate__(self, state)
:从状态恢复对象。
例子:
假如我们想保存对象的某些字段而排除其他字段。在 __getstate__()
方法中,我们需要:
-
复制当前对象状态(由服务字段
__dict__
指定)到一个单独的变量——字典state
。 - 删除其中不需要序列化的字段。
- 返回得到的对象作为
__getstate__()
函数的结果。
import pickle
class CustomClass:
def __init__(self, value):
self.value = value
self.internal_state = "internal"
def __getstate__(self):
state = self.__dict__.copy()
del state['internal_state'] # 排除内部状态
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.internal_state = "restored internal" # 恢复内部状态
def __repr__(self):
return f"CustomClass(value={self.value}, internal_state={self.internal_state})"
# 创建对象
obj = CustomClass(42)
print("原始对象:", obj)
# 对象序列化
serialized_obj = pickle.dumps(obj)
print("序列化对象:", serialized_obj)
# 对象反序列化
deserialized_obj = pickle.loads(serialized_obj)
print("反序列化对象:", deserialized_obj)
在反序列化时,在 __setstate__()
函数中,我们做两件事情:
-
使用
update()
方法更新对象的当前状态。 -
字段
internal_state
(以及其他不可序列化字段)获得新值。
GO TO FULL VERSION