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