我有一个递归生成器函数,它创建一棵 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/

10-13 21:35