我正在浏览serge pygame engine中的一些代码,然后我在serge.serialize
中找到了我无法绕过的东西:
def __setstate__(self, state=None):
"""Initialize the object to the given state for unpickling"""
self.initial_properties = Bag()
#
# Initialize first from the defaults and then from the live state
for this_state in (self.__class__._getProperties(), state):
if this_state:
for name, value in this_state:
setattr(self, name, value)
setattr(self.initial_properties, name, value)
此方法是从Serializable
对象中检索的。我感到困惑的是,state
中的__setstate__
参数的默认值为None
。为什么在取消对象时不会将状态发送到__setstate__
,在什么情况下这会有用呢?
答案 0 :(得分:4)
如果您的课程完全依赖__getstate__
/ __setstate__
进行腌制,则此功能无效。
正如__setstate__
上的文档解释:
取消排版时,如果类定义了
__setstate__()
,则会以未选中的状态调用它...如果__getstate__()
返回false值,则取消时不会调用__setstate__()
方法。< / p>
因此,如果您的__getstate__
返回None
,则会在__setstate__
时将其传回给您;你不会被召唤。
但请注意,在2.x version中,对于经典类而言并非如此。对于经典类,“如果一个类定义__getstate__()
和__setstate__()
,则状态对象不必是字典,这些方法可以做他们想要的。” (事实上,我相信在某些情况下,任何虚假值都会转变为{}
,但这种情况并没有很好地记录,但同样的if
语句会处理... {/ p>
但是,这并不能解释为什么你需要一个默认值......如果你能得到None
,你肯定需要编写处理None
的代码......但是你没有需要编写完全没有参数的代码,对吗?
但是,你有理由这样做。
首先,请注意,此特定类的__setstate__
比平常更多:它首先从默认值开始,然后从实时状态初始化“。因此,单元测试非常有用,从默认值开始初始化是有效的。
除此之外,如果您定义自定义__reduce__
方法和unreducer,则没有理由必须遵循与默认的unreducer完全相同的规则。或者当然没有理由它必须完全调用__setstate__
- 但是,如果您正在构建一个您期望用户进行子类化的基类,那么您的unreducer就可以工作了与默认设置一样,因此您的用户只需覆盖__setstate__
,而不是添加自己的整个__reduce__
实施。
同样,如果您在pickle
/ copyreg
之上构建自己的序列化程序,而不是按原样使用它,那么您的代码就不必使用完全相同的规则pickle
。同样,它没有理由使用甚至类似的规则,但这样做可能会让您的用户更容易扩展您的类。
这些是否适用于serge
,我不知道,但它们都可以轻松应用于您可能想要构建的各种类型。