在python中,path + = [newpath]和path = path + [newpath]之间有什么区别?

问题描述 投票:0回答:3

在下面的函数中,当我使用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'))
python
3个回答
3
投票

这里有两件事:

首先,你在path=[]定义中的find_path是一个mutable default argument,如果你不期待它,它有一个非常令人惊讶的行为。简短的版本是path的默认值不是每次都是新的[],而是每次都是相同的[]

其次,path = path + [start]将名称path重新命名为由连接创建的新list对象,而path += [start]则改变list指向的现有path对象。我可以想到的最好的资源来学习更多关于这种区别的文章是Facts and myths about Python names and values

两者的结合意味着您每次都在改变相同的列表;如果您更改其中任何一个,您将获得单独的列表对象,而不会看到此问题。


0
投票

问题来自于在find_path定义中使用可变值作为默认参数。

  • 当你使用path += [start]时,你实际上改变了path的默认值
  • 当你使用path = path + [start]时,你实际上将path参数存储在本地path变量中,然后再进行更改。

更多细节here


0
投票

遗憾的是,对于列表,Python重载+=意味着与list.extend相同(在所有情况下而不仅仅是当差异不可见时),因此它将使用RHS就地扩展LHS,而正常的二进制+将创建一个品牌新的列表对象,复制LHS,然后复制RHS。

这在这里是显而易见的,因为在Python中,默认值是在模块解析期间创建的并且绑定到函数本身,每次调用函数时都不会获得新值。因此,如果您就地修改path(这是+=所做的),它仍然在函数的调用之间。

© www.soinside.com 2019 - 2024. All rights reserved.