【问题标题】:Is it possible to force cPickle to use breadth-first rather than depth-first recursion?是否可以强制 cPickle 使用广度优先而不是深度优先递归?
【发布时间】:2011-03-05 21:17:18
【问题描述】:

我意识到答案很可能是否定的!

基本上,我有一个图形(节点和边类型),它代表一个正方形网格;每个节点对象包含对该节点具有边缘的每个其他节点的引用,这似乎意味着当使用 cPickle.dump 序列化图形时,它会以深度优先方式遍历图形中的每个节点,这意味着对于一个井- 表示 16x16 网格的连接图,它有效地将其视为 256 级深度的数据结构。这意味着较大的网格很快就会超过默认的最大 Python 递归深度,特别是因为实验表明,似乎需要在堆栈上进行大约 4 次调用才能将数据结构额外一层。

问题是,我还有一个 dict-of-dicts 引用该图的方式允许我使用笛卡尔坐标来查找特定节点(例如“node = nodes[3][6]” )。所以从概念上讲,它根本不是一个高度嵌套的数据结构,它是一个相当平坦的结构,恰好有很多横向引用,但似乎 cPickle 完全是深度优先的(我理解这是迄今为止最简单的方法工作)。

现在,我知道了 sys.setrecursionlimit(),并且我已经做了一些实验来找出我需要为什么大小的图形设置限制,所以这是“最简单”的选项。我知道我可以退出节点到节点的链接并依靠dict-of-dicts来维护网格和单独的平面结构来维护边缘权重,但是有各种原因我想避免那 - 尤其是节点到节点的链接允许更直观地使用数据结构。我相信从我所读到的内容中,我应该能够提供我自己的 __getstate____setstate__ 实现并覆盖酸洗功能,但显然这是一项非常重要的工作。如果有办法让 cPickle(或 pickle,我不挑剔!)使用广度优先遍历,它应该可以很简单地解决问题!

【问题讨论】:

    标签: python recursion pickle


    【解决方案1】:

    毕竟编写一个合适的__getstate__() 方法似乎并没有那么复杂。尝试类似

    class Node(object):
        def __getstate__(self):
            state = self.__dict__.copy()
            state.pop("neighbours")
            return state
    

    这将腌制Node 实例的所有属性,除了neighbours 属性,我假设它包含指向邻居的链接。 (您不需要__setstate__() 方法。)

    解压整个图后,您必须在所有节点上重新创建到邻居的链接,但这也不应该那么困难。

    【讨论】:

    • 我更担心编码然后重新构建边缘数据,但我确实完全忘记了 __dict__ 属性,而且我不确定我是否知道 dict 有一个 'pop ' 方法,非常感谢您的信息!出于兴趣,为什么在这种情况下使用“pop”而不是“del”——只是为了稳健? (我想我必须在 __setstate__ 中完成这项工作,因为我无法控制类被腌制的代码。)
    • @Jake:想想看,del 似乎比使用.pop() 更自然,但实际上并不重要。关键是您可以在酸洗之前以某种方式删除与邻居的链接,然后重建它们,整个事情应该不会那么困难。
    猜你喜欢
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 2012-08-29
    相关资源
    最近更新 更多