【问题标题】:Return value of a intermediate step of a recursion递归中间步骤的返回值
【发布时间】:2018-02-14 17:17:02
【问题描述】:

有一个简单的脚本旨在确定xy 之间的路径存在。

通过实现,我想检索一些中间值,但在递归调用中迷失了方向。基本上,有人可以帮助区分这两种实现之间的差异吗?为什么他们提供了不同的回报?

快速说明:唯一的区别是标志部分。

# i.e., adj: {1: {2}, 2: {1, 3}, 3: {2, 5}, 4: {5}, 5: {3, 4}, 11: {12}, 12: {11, 15}, 15: {12}}

实施1

def dfs(adj, x, y, visited=None, flag=[]):
    if visited is None:
        visited = set()
    if x == y:
        flag.append(True)
    if x not in visited:
        visited.add(x)
    for neigh in adj[x]:
        if neigh not in visited:
            dfs(adj, neigh, y, visited, flag)

    return flag

现在:

dfs(adj, 1, 5) 

返回:

[True]

实施 2

def dfs(adj, x, y, visited=None, flag=False):
    if visited is None:
        visited = set()
    if x == y:
        flag = True
    if x not in visited:
        visited.add(x)
    for neigh in adj[x]:
        if neigh not in visited:
            dfs(adj, neigh, y, visited, flag)

    return flag

和:

dfs(adj, 1, 5) 

返回:

False

已编辑

感谢您的回答,我相信它解决了递归调用的参数重置问题。但是对于问题的另一面,我还是需要一些帮助,即递归调用什么时候会覆盖一个参数的值并沿途继承到顶部?

让我用上面的例子来详细说明。以下结果是调试implementation 1implementation 2跟踪的一些prints,按照完成时间排序。

Intermediate_func       Implementation1   Implementation2    
dfs(adj, 4, 5)           [True]           True  
dfs(adj, 5, 5)           [True]           True  
dfs(adj, 3, 5)           [True]           False  
dfs(adj, 2, 5)           [True]           False 
dfs(adj, 1, 5)           [True]           False  

观察到[True] 一直被复制到dfs(adj, 1, 5)。按照执行顺序 (Implementation 1),dfs(adj, 1, 5)dfs(adj, 2, 5)dfs(adj, 3, 5) 被初始化为 [],直到它看到 dfs(adj, 5, 5)。不知何故,来自dfs(adj, 5, 5)[True] 值被保留并传递给dfs(adj, 1, 5)。为什么不能将Implementation 2 中的True 值复制到dfs(adj, 1, 5)

【问题讨论】:

    标签: python python-3.x recursion immutability


    【解决方案1】:

    永远不要使用可变的默认参数。 Python 只创建一次函数对象。这意味着flag=[] 仅被创建一次并使用所有对dfs 的调用。

    将您的第一个实现更改为:

    def dfs(adj, x, y, visited=None, flag=None):
        flag = []
        if visited is None:
            visited = set()
        if x == y:
            flag.append(True)
        if x not in visited:
            visited.add(x)
        for neigh in adj[x]:
            if neigh not in visited:
                dfs(adj, neigh, y, visited, flag)
    
        return flag
    

    现在:

    dfs(adj, 1, 5)
    

    返回:

    []
    

    所以问题是保留True(实现1)与False的列表,每个(递归)函数(实现2)都被重置。将列表重置为空列表使两个实现等效。

    如果要将信息移动到递归调用中,则需要移动返回的标志:

    def dfs(adj, x, y, visited=None, flag=False):
        if visited is None:
            visited = set()
        if x == y:
            flag = True
        if x not in visited:
            visited.add(x)
        for neigh in adj[x]:
            if neigh not in visited:
                #  save returned flag here
                flag = dfs(adj, neigh, y, visited, flag)
    
        return flag
    

    现在:

    dfs(adj, 1, 5)
    

    返回:

    True
    

    【讨论】:

      猜你喜欢
      • 2021-01-09
      • 1970-01-01
      • 2016-05-28
      • 2014-05-01
      • 1970-01-01
      • 2021-03-14
      • 2022-11-05
      • 2012-12-08
      • 2022-01-17
      相关资源
      最近更新 更多