python - 暂停(序列化)和恢复递归生成器堆栈的解决方法?

标签 python recursion tree generator python-3.3

我有一个递归生成器函数,它创建一个 ChainMap 上下文树,并最终在树的末尾对上下文执行某些操作。看起来像这样(parent_context 是一个 ChainMap,hierarchy 是一个列表):

def recursive_generator(parent_context, hierarchy):
    next_level = hierarchy[0]
    next_level_contexts = get_contexts(next_level) # returns a list of dicts

    for context in next_level_contexts:
        child_context = parent_context.new_child().update(context)
        if next_level == hierarchy[-1]:
            yield do_something(**child_context)
        else:
            yield from recursive_generator(child_context, hierarchy[1:])

现在我想标记层次结构的一个级别,以便操作在完成该级别后暂停,将状态序列化到磁盘,以便稍后从它停止的地方获取。有没有办法在不失去递归的优雅的情况下做到这一点?

我知道你不能 pickle 生成器,所以我考虑重构为一个迭代器对象。但我认为 yield from 对于这里的递归是必要的(编辑:至少没有一些繁琐的堆栈管理),所以我认为它需要是一个生成器,不是吗?有解决办法吗?

最佳答案

您似乎正在使用 DFS 探索一棵树。所以你可以在内存中构建树并使 DFS 显式。然后只需存储树并在最左边的节点重新启动(我想?)。

这实际上是“繁琐的堆栈管理”,但它有一张有助于实现它的漂亮图片(至少对我而言,将您的问题视为树的 DFS 使得实现看起来相当明显 - 在我想到之前就像那样,它看起来很复杂 - 但我可能会遗漏一些东西)。

抱歉,如果这很明显且不够......

[编辑]

class Inner:

    def __init__(self, context, hierarchy):
        self.children = []
        next_level = hierarchy[0]
        next_level_contexts = get_contexts(next_level)
        for context in next_level_contexts:
            child_context = parent_context.new_child().update(context)
            if next_level == hierarchy[-1]:
                self.children.append(Leaf(context))
            else:
                self.children.append(Inner(child_context, hierarchy[1:]))

    def do_something(self):
        # this will do something on the left-most leaf                         
        self.children[0].so_something()

    def prune(self):
        # this will remove the left-most leaf                                  
        if isinstance(self.children[0], Leaf):
            self.children.pop(0)
        else:
            self.children[0].prune()
            if not self.children[0]:
                self.children.pop(0)

    def __bool__(self):
        return bool(self.children)

class Leaf:

    def __init__(self, context):
        self.context = context

    def do_something(): 
        do_something(**self.context)

上面的代码还没有经过测试。我最终为节点使用了类,因为元组看起来太困惑了。您通过创建父节点来创建树。然后您可以通过调用 do_something 来“做某事”,之后您将需要使用 prune 删除“完成”的叶子:

tree = Inner(initial_context, initial_hierarchy)
while tree:
    tree.do_something()
    tree.prune()

我很确定它会包含错误,但希望它足以展示这个想法。抱歉,我不能做更多,但我需要重新种植植物....

ps 有趣的是,您可以使用生成器编写代码,但不知道 DFS 是什么。您可能会喜欢阅读“算法设计手册”——它既是教科书又是引用书,它不会把您当成白痴(我也没有接受过计算机科学方面的正规教育,但我认为这是一本好书)。

[编辑为先更改为最左侧,我认为这是您之前的设置]

alko 有一个很好的观点...

关于python - 暂停(序列化)和恢复递归生成器堆栈的解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19745459/

相关文章:

python - 插入缺失值 2d python

python - 数组的 sklearn DeprecationWarning 真值

PHP mysql创建树状层次结构及其计数

java - 使用 XStream 创建不同对象的列表

python - 如何确保在ES API中捕获所有数据?

java - 智能卡 ATR 和选择文件命令

algorithm - 方案中的扩展欧几里得算法

java - 给定斐波那契递归函数创建内存算法

python - Python 中的递归回溯——在秤上平衡重量

python - 在 Python 中动态评估简单的 boolean 逻辑