我正在使用从the ordered_set module链接到的this answer的1.2版(当前是最新版本)。我一直有一些奇怪的行为,并追溯到此:
from ordered_set import OrderedSet
import pickle
os_orig = OrderedSet()
print os_orig # 'OrderedSet'
print os_orig.items # '[]'
pickled = pickle.dumps(os_orig)
loaded = pickle.loads(pickled)
print loaded
引发
AttributeError: 'OrderedSet' object has no attribute 'items'
。如果OrderedSet不为空,则一切正常。不幸的是,当我要 pickle 时,我在这里头不停-怎么了?
编辑:我应该补充一点,该模块似乎支持 pickle 。在自述文件中:“添加了
__getstate__
和__setstate__
,以便可以将其 pickle ” 最佳答案
当集合为空时,对OrderedSet
的 pickle 支持将中断,因为__getstate__
返回的状态实质上为空:
>>> OrderedSet().__getstate__()
[]
当
pickle
的返回值为空时,__setstate__
模块最终在不再次加载pickle时不调用__getstate__
。不调用__setstate__
意味着OrderedSet.__init__()
方法永远不会被调用,并且您的对象已损坏。参见 __setstate__
documenation:空列表是错误的值。
作者必须仅用 pickle 非空
OrderedSet()
实例进行了测试,效果很好。您可以通过替换
__getstate__
和__setstate__
方法来解决此问题:def __getstate__(self):
return (list(self),)
OrderedSet.__getstate__ = __getstate__
def __setstate__(self, state):
if isinstance(state, tuple):
state = state[0]
self.__init__(state)
OrderedSet.__setstate__ = __setstate__
现在,返回一个非空的1元素元组,甚至对于空集也强制
pickle
调用__setstate__
。 __setstate__
仍将接受以前的 pickle 格式,即列表对象。我将其报告为bug with the project,因为已解决后关闭。