递归的中间步骤的返回值

时间:2018-02-14 17:17:03

标签: python python-3.x recursion immutability

有一个简单的脚本旨在确定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

被修改

感谢您的回答,我相信它解决了递归调用的参数重置问题。但是对于问题的另一面,我仍然需要一些帮助,也就是说,递归调用何时覆盖参数的值并继承到顶部?

让我详细说明上面的例子。以下结果是从调试printimplementation 1跟踪的一些implementation 2,根据其完成时间排序。

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)。不知何故,来自[True]的{​​{1}}值会保留并传递给dfs(adj, 5, 5)。为什么不能将dfs(adj, 1, 5)的{​​{1}}值复制到True

1 个答案:

答案 0 :(得分:0)

永远不要使用可变的默认参数。 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