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

2024-04-25 00:38:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个递归生成器函数,它创建了一个链式映射上下文树,并最终对树末尾的上下文执行某些操作。看起来像这样(parent_context是一个链表,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对于这里的递归是必要的(编辑:至少没有一些繁琐的堆栈管理),所以我认为它需要一个生成器,不是吗?有解决办法吗?在


Tags: 函数fromchildhierarchycontext级别generatorlevel
2条回答

我最后要做的是:

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 child_context
        else:
            yield from recursive_generator(child_context, hierarchy[1:])

def traverse_tree(hierarchy):
    return list(recursive_generator(ChainMap(), hierarchy)

def do_things(contexts, start, stop):
    for context in contexts[start:stop]:
        yield do_something(**context)

然后我可以pickle由traverse_tree返回的列表,然后加载它并用do_things分段运行它。当然,这些都是在一个有更多内容的课堂上进行的,但这才是重点。在

你好像在用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删除“done”叶:

^{pr2}$

我很确定它会包含bug,但希望它足够展示这个想法。抱歉,我不能做更多,但我需要报告植物。。。。在

有趣的是,你可以用生成器编写代码,但不知道DFS是什么。你可能喜欢读“算法设计手册”—它是教科书和参考资料的一部分,它不会把你当傻瓜(我也没有受过正规的计算机科学教育,我认为这是一本好书)。在

我最想改变的是什么

alko有一个很好的观点。。。在

相关问题 更多 >