【问题标题】:What is the difference between path += [newpath] and path = path + [newpath] in pythonpython中path += [newpath]和path = path + [newpath]有什么区别
【发布时间】:2019-03-12 13:54:37
【问题描述】:

在下面的函数中,当我使用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


【解决方案1】:

这里发生了两件事:

首先,您对find_path 的定义中的path=[]mutable default argument,如果您没有预料到,它的行为非常令人惊讶。简而言之,path 的默认值不是每次都是新的[],而是每次都一样[]

其次,path = path + [start] 重新绑定名称 path 到由串联创建的新 list 对象,而 path += [start] 改变现有的 list path 指向的对象。文章Facts and myths about Python names and values 是我能想到的更多了解这种区别的最佳资源。

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

【讨论】:

    【解决方案2】:

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

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

    更多详情here

    【讨论】:

      【解决方案3】:

      遗憾的是,对于列表 Python 重载 +=list.extend 的含义相同(在所有情况下,而不仅仅是在差异不可见时),因此它将使用 RHS 就地扩展 LHS ,而普通二进制+ 将创建一个全新的列表对象,将 LHS 复制到其中,然后将 RHS 复制到其中。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-19
        • 2018-01-02
        • 1970-01-01
        • 2018-11-07
        • 2013-12-25
        • 1970-01-01
        • 2020-09-03
        相关资源
        最近更新 更多