如果你想让你的类在反pickle时调用 __init__ ,你可以定义 __getinitargs__(self),它会返回一个参数元组,这个元组会传递给 __init__ 。注意,这个方法只能用于旧式类。 __getnewargs__(self)
对新式类来说,你可以通过这个方法改变类在反pickle时传递给__new__ 的参数。这个方法应该返回一个参数元组。
__getstate__(self)
你可以自定义对象被pickle时被存储的状态,而不使用对象的 __dict__ 属性。 这个状态在对象被反pickle时会被 __setstate__ 使用。
__setstate__(self)
当一个对象被反pickle时,如果定义了 __setstate__ ,对象的状态会传递给这个魔法方法,而不是直接应用到对象的 __dict__ 属性。这个魔法方法和 __getstate__ 相互依存:当这两个方法都被定义时,你可以在Pickle时使用任何方法保存对象的任何状态。
__reduce__(self)
当定义扩展类型时(也就是使用Python的C语言API实现的类型),如果你想pickle它们,你必须告诉Python如何pickle它们。 __reduce__ 被定义之后,当对象被Pickle时就会被调用。它要么返回一个代表全局名称的字符串,Pyhton会查找它并pickle,要么返回一个元组。这个元组包含2到5个元素,其中包括:一个可调用的对象,用于重建对象时调用;一个参数元素,供那个可调用对象使用;被传递给 __setstate__ 的状态(可选);一个产生被pickle的列表元素的迭代器(可选);一个产生被pickle的字典元素的迭代器(可选);
__reduce_ex__(self)
__reduce_ex__ 的存在是为了兼容性。如果它被定义,在pickle时 __reduce_ex__ 会代替 __reduce__ 被调用。 __reduce__ 也可以被定义,用于不支持 __reduce_ex__ 的旧版pickle的API调用。
13.3. 一个例子
我们的例子是 Slate ,它会记住它的值曾经是什么,以及那些值是什么时候赋给它的。然而 每次被pickle时它都会变成空白,因为当前的值不会被存储:
import time class Slate: '''存储一个字符串和一个变更日志的类 每次被pickle都会忘记它当前的值''' def __init__(self, value): self.value = value self.last_change = time.asctime() self.history = {} def change(self, new_value): # 改变当前值,将上一个值记录到历史 self.history[self.last_change] = self.value self.value = new_value) self.last_change = time.asctime() def print_change(self): print 'Changelog for Slate object:' for k,v in self.history.items(): print '%s\t %s' % (k,v) def __getstate__(self): # 故意不返回self.value或self.last_change # 我们想在反pickle时得到一个空白的slate return self.history def __setstate__(self): # 使self.history = slate,last_change # 和value为未定义 self.history = state self.value, self.last_change = None, None14. 总结
这本指南的目标是使所有阅读它的人都能有所收获,无论他们有没有使用Python或者进行面向对象编程的经验。如果你刚刚开始学习Python,你会得到宝贵的基础知识,了解如何写出具有丰富特性的,优雅而且易用的类。如果你是中级的Python程序员,你或许能掌握一些新的概念和技巧,以及一些可以减少代码行数的好办法。如果你是专家级别的Python爱好者,你又重新复习了一遍某些可能已经忘掉的知识,也可能顺便了解了一些新技巧。无论你的水平怎样,我希望这趟遨游Python特殊方法的旅行,真的对你产生了魔法般的效果(实在忍不住不说最后这个双关)。
Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx