在下面的函数中,当我使用path = path + [start]
时,我将得到结果['A', 'B', 'E']
,但是当我使用path += [start]
时,我将得到结果['A', 'B', 'D', 'E']
。为什么?
我的代码:
graph1 = {'A':['B','C'],
'B':['A','D','E'],
'C':['A','F'],
'D':['B'],
'E':['B','F'],
'F':['C','E']}
def find_path(graph,start,end,path=[]):
path = path + [start]
if start == end:
return path
if start not in graph:
return None
for node in graph[start]:
if node not in path:
newpath = find_path(graph,node,end,path)
if newpath:
return newpath
return None
print(find_path(graph1,'A','E'))
答案 0 :(得分:3)
这里发生了两件事:
首先,您对path=[]
的定义中的find_path
是mutable default argument,如果您不期望这样做,它的行为将非常令人惊讶。简短的版本是path
的默认值并非每次都是新的[]
,而是每次相同 []
。
第二,path = path + [start]
将名称path
重新绑定到由串联创建的新list
对象,而path += [start]
将< / em> list
指向的现有path
对象。为了进一步了解这种区别,我可以想到的最佳资源是文章Facts and myths about Python names and values。
两者的组合意味着您每次都在更改相同列表;如果您更改它们中的任何一个,您将获得单独的列表对象,并且不会看到此问题。
答案 1 :(得分:0)
问题来自find_path
定义中使用可变值作为默认参数。
path += [start]
时,实际上是在更改默认值
的path
path = path + [start]
时,您实际上存储了
更改之前,请在局部path
中使用path
个参数。更多细节here
答案 2 :(得分:0)
不幸的是,对于列表,Python重载+=
的含义与list.extend
相同(在所有情况下,而不仅仅是当差异不可见时),因此它将用RHS 就地,而普通二进制文件+
将创建一个全新的列表对象,在其中复制LHS,然后在其中复制RHS。
这在这里很明显,因为在Python中,默认值是在模块解析期间创建的,并且绑定到函数本身,因此每次调用该函数时都不会得到新值。因此,如果您就地修改path
(这是+=
所做的),它将保留在函数调用之间。