You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:30:40