Python递归函数中网格路径列表存储异常问题求助
解决递归存储网格路径时列表全空的问题
嘿,我之前也碰到过一模一样的坑!递归能正常打印路径,但存到列表里就全空,核心原因其实是Python中列表是可变对象,传递的是引用,你在回溯时修改了同一个列表对象,最后所有存在结果里的都是这个被清空后的列表引用。
问题根源拆解
举个典型的错误代码例子(应该和你写的类似):
def find_paths(grid, start, end, path, result): path.append(start) # 到达终点时添加路径到结果 if start == end: result.append(path) # 这里加的是path的引用,不是独立副本! return # 假设只能向右或向下移动 x, y = start if x < len(grid) - 1: find_paths(grid, (x+1, y), end, path, result) if y < len(grid[0]) - 1: find_paths(grid, (x, y+1), end, path, result) # 回溯:移除当前节点 path.pop() # 调用示例 grid = [[0]*3 for _ in range(3)] result = [] find_paths(grid, (0,0), (2,2), [], result) print(result) # 输出:[[], [], [], [], []] 全空!
你打印路径时是在start == end的瞬间输出,此时路径是完整的,但result.append(path)只是把路径列表的引用存了进去。后续回溯的path.pop()会修改这个列表,等递归全部结束,所有引用指向的都是被清空后的空列表。
两种修复方案
方案1:添加到结果时存路径副本
只需要修改添加结果的那一行,把当前路径的副本存入结果,而不是引用:
if start == end: result.append(path.copy()) # 或者 list(path) / path[:] return
这样每个路径都是独立的列表,后续回溯修改原path不会影响已经存入结果的副本。
方案2:递归时传递路径副本(无需手动回溯)
另一种思路是每次递归调用时创建新的路径列表,这样就不用手动pop回溯,每个递归分支有自己独立的路径:
def find_paths(grid, start, end, path, result): new_path = path + [start] # 创建新列表,包含当前路径+当前节点 if start == end: result.append(new_path) return x, y = start if x < len(grid) - 1: find_paths(grid, (x+1, y), end, new_path, result) if y < len(grid[0]) - 1: find_paths(grid, (x, y+1), end, new_path, result) # 调用示例 grid = [[0]*3 for _ in range(3)] result = [] find_paths(grid, (0,0), (2,2), [], result) print(result) # 正常输出所有路径:[[(0,0), (0,1), (0,2), (1,2), (2,2)], ...]
总结
本质就是要区分可变对象的引用传递和值传递,在递归处理路径这类需要保留快照的场景中,一定要记得创建列表副本,避免后续修改影响已存储的结果。我当初踩这个坑的时候,盯着空列表愣了好久,后来才反应过来是引用在搞鬼😅
内容的提问来源于stack exchange,提问作者Lithium
相关产品推荐
相关产品推荐

