Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 添加和+;=为列表提供不同的结果(深度优先搜索)_Python_List_Depth First Search - Fatal编程技术网

Python 添加和+;=为列表提供不同的结果(深度优先搜索)

Python 添加和+;=为列表提供不同的结果(深度优先搜索),python,list,depth-first-search,Python,List,Depth First Search,我一直试图理解深度优先搜索,并使用各种在线来源获得以下代码: graph = {'A': ['B', 'D'], 'B': ['E'], 'C': [], 'D': ['C', 'E'], 'E': ['H', 'I', 'J'], 'F': [], 'G': [], 'H': ['F'], 'I': [], 'J': ['G']} def dfs(graph, start, end, path=None): if path == None:

我一直试图理解深度优先搜索,并使用各种在线来源获得以下代码:

graph = {'A': ['B', 'D'], 'B': ['E'], 'C': [], 'D': ['C', 'E'], 
         'E': ['H', 'I', 'J'], 'F': [], 'G': [], 'H': ['F'], 
         'I': [], 'J': ['G']}

def dfs(graph, start, end, path=None):
    if path == None:
        path = []
    path = path + [start]
    paths = []
    if start == end:
        return [path]
    for neighbour in graph[start]:
        if neighbour not in path:
            paths.extend(dfs(graph, neighbour, end, path))
    return paths

print(dfs(graph, 'A', 'G'))
这将输出所需的结果:

[['A', 'B', 'E', 'J', 'G'], ['A', 'D', 'E', 'J', 'G']]
但是,当我用
path+=[start]
替换行
path+=[start]
(或者
path.extend([start])
,我知道它也做同样的事情)时,我得到了以下输出:
[[A',B',E',H',F',I',J',G',D',C']

我知道这与操作的不同有关,但我真的不明白它在这里是如何应用的。有人能解释一下吗

path = path + [start]

path += [start]  # or path.extend([start])
用于列表(和其他可变类型),因为它重新创建了
路径的新引用(隐式地表示您想要的内容,您不想写入以前的引用)

重复使用相同的引用,因为您在循环中多次传递
路径
(不复制):

因此,如果某个其他对象将其存储在存储器中,您将更改这两个列表:不是相同的行为,也不是您想要的行为

当然,您可以执行
path.extend(dfs(graph,neighbor,end,path.copy())
,但这违反了调用者的最小补偿原则(调用者不希望修改最后一个参数)

我的忠告是:

  • 如果您想要性能,并且不关心是否重用引用,请始终对列表使用
    +=
    ,因为它只是扩展列表。
    +
    操作符创建一个新的列表并进行复制,这非常慢
  • 当对
    列表类型使用
    path=path+something
    时,请始终为将来的维护人员(包括您自己!)添加注释,而不要使用
    +=
    对其进行优化
可能是一些更明确、更等效的代码:

path = path.copy() # or path[:], or list(path)...: force creation of a new reference to break dependency with passed parameter
path += [start]
另请注意:它不适用于
str
tuple
类型,因为由于字符串不变性,即使
+=
也会创建一个新引用。没有与字符串共享引用的风险,因此在此处使用
tuple
而不是
list
也可以解决此问题:

if path == None:
    path = tuple()
path += (start,)  # += creates a new path reference, cos path is a tuple, immutable

(但不要期望
+=
的性能更高,在这种情况下,可以进行复制)

您应该避免设置默认的可变参数,如
path=[]
,这是python()中常见的问题!谢谢你的教训:-)我没看到。但问题在编辑后仍然存在,可能是因为OP没有使用带有默认参数的
dfs
,而是这样。这是一个旁白(在本例中不是一个重要的旁白,因为函数只被调用一次),但它教会了我一些我应该知道的东西!是的,问题仍然存在。当前代码输出:
[[['A','B','E','H','F','I','J','G','D','C']
而不是
[['A','B','E','J','G'],['A','D','E','J','G']]
如问题中所述。这是一个很好的建议,但没有回答OP为什么会有所不同的问题results@ShpielMeister该代码中基本上有两个大错误,这让读者感到困惑。现在OP修正了论点一(除了…,它没有改变任何东西),我的答案是:)我只是喜欢那个网站:)谢谢。否则,它会是另一个令人悲伤的复制品
path = path.copy() # or path[:], or list(path)...: force creation of a new reference to break dependency with passed parameter
path += [start]
if path == None:
    path = tuple()
path += (start,)  # += creates a new path reference, cos path is a tuple, immutable