微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

递归堆栈帧在 python 的 Visual Studio 调试器中具有相同的值

如何解决递归堆栈帧在 python 的 Visual Studio 调试器中具有相同的值

我试图在 python 中对我制作的图形类进行深度优先递归搜索。由于某种未知原因,我未能通过断言级别的测试:AssertionError: None not found in [[1,2,4,6],[1,7,6]],我理解该错误的含义,我不打算直接询问算法,而是询问我注意到的其他问题。

使用 VS Code python 调试器,我决定检查运行中的代码,我注意到每次新调用都会将新的堆栈帧推送到堆栈中(参见图片),它们共享相同的“访问”值(设置)和“路径”(列表)实例(完全出乎意料且令人困惑)。我添加一个 callnumber 虚拟变量作为健全性检查,以确保我正确使用了调试器,而且我确实如此。

我不知道为什么我没有早点发现它,尤其是因为我在 C 和内存管理方面做了很多工作。这些对象显然是放在堆上并通过引用传递的,因此并不是真正独立的实例,对吗?

有没有办法让这些基于堆栈的变量?我知道这是不推荐的,因为存在堆栈溢出的风险(没有双关语)并且不能很好地利用空间。

既然我明白了发生了什么,我想知道你是否有一些关于我如何使这个算法运行的指示(这次是双关语),因为这种方法是基于堆的,所以不起作用?我不需要解决它,只需要一些提示或线索,可以产生更深入思考的东西。

顺便说一句,我一直在努力提高阅读和理解文档的能力。我喜欢文档是我第一个去的,但是当我用谷歌搜索 python 时,它们总是接近底部随机教程,与其他语言不同。我刚刚去了官方 page on built in types搜索了诸如堆或内存之类的词来查找列表和字典,但我没有找到解释这些对象的位置,它们如何增长或调整大小等的信息,尽管这可能很明显对于有经验的程序员来说是隐含的,但无论如何这里是我的代码

class Graph:
    def __init__(self):
        self.vertices = {}
    def add_vertex(self,vertex_id):
        self.vertices[vertex_id] = set()
    def add_edge(self,v1,v2):
        self.vertices[v1].add(v2)
    # more functions

    def dfs_recursive(self,starting_vertex,destination_vertex,visited = set(),path=[]):
        """
        Return a list containing a path from
        starting_vertex to destination_vertex in
        depth-first order.

        This should be done using recursion.
        """
        result = None
        path.append(starting_vertex)
        visited.add(starting_vertex)
        if starting_vertex == destination_vertex:
            return path
        for neighbor in self.vertices[starting_vertex]:
            if neighbor not in visited:
                visited.add(neighbor)
                result = self.dfs_recursive(neighbor,visited,path,callnumber+1)
        return result

enter image description here

编辑:由于 rioV8 的输入,解决了算法。 这是我的代码

    def dfs_recursive(self,visited = None,path=None,callnumber=1):

        path = path or []
        visited = visited or set()
        path.append(starting_vertex)
        visited.add(starting_vertex)
        if starting_vertex == destination_vertex:
            return path
        for neighbor in self.vertices[starting_vertex]:
            if neighbor not in visited:
                result = self.dfs_recursive(neighbor,visited.copy(),path[:],callnumber+1)
                if result is not None and result[-1] == destination_vertex:
                    return result
        return None

解决方法

不要使用可修改的对象作为函数默认参数。

它们是在函数编译时创建的,而不是在函数调用时创建的。并在每次调用时重复使用。

使用 None 并在函数内部创建可修改的。

并在递归调用中制作可修改的副本。

def dfs_recursive(self,starting_vertex,destination_vertex,visited=None,path=None):
    visited = visited or set()
    path = path or []
    # rest of function
    result = self.dfs_recursive(neighbor,visited.copy(),path[:],callnumber+1)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。