我正在使用从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,因为已解决后关闭。

10-06 10:36
查看更多