Python 路径之间的差异=路径+;[节点1],路径+;=[node1]和path.append(node1)

Python 路径之间的差异=路径+;[节点1],路径+;=[node1]和path.append(node1),python,dictionary,graph,path,set,Python,Dictionary,Graph,Path,Set,我正试图找出两者之间的区别 路径=路径+[节点1] 路径+=[节点1] path.append(节点1) 对于path=path+[node1],我得到的是正确的路径,但不是其他两个 def find_path(self, node1, node2, path = []): """ Finds any path from node1 to node2 which may not be the shortest """ path = path + [node1] if n

我正试图找出两者之间的区别

  • 路径=路径+[节点1]
  • 路径+=[节点1]
  • path.append(节点1)
  • 对于path=path+[node1],我得到的是正确的路径,但不是其他两个

    def find_path(self, node1, node2, path = []):
        """ Finds any path from node1 to node2 which may not be the shortest """
    
        path = path + [node1]
        if node1 == node2:
            return path
        if node1 not in self._graph:
            return None
        for node in self._graph[node1]:
            if node not in path:
                new_path = self.find_path(node, node2, path)
                if new_path:
                    return new_path
        return None
    
    使用可变默认参数时,需要非常小心。请看

    行为差异的原因是

    path = path + [node1]
    
    创建新列表并将其绑定到名称
    路径
    。其他两个备选方案修改绑定到
    path
    的现有列表


    正如链接问题所解释的,默认参数是在编译函数定义时创建的,而不是在调用函数时创建的。在递归函数中使用可变默认参数时,这一点尤其重要,因为这意味着默认参数不会在每次顶级递归调用时重置

    如果您不想要使用可变默认参数所提供的“特殊”行为,可以执行以下操作:

    def find_path(self, node1, node2, path=None):
        if path is None:
            path = []
        # rest of code
    
    如果
    None
    path
    的有效参数,则需要使用其他一些哨兵,例如

    sentinel = object()
    def find_path(self, node1, node2, path=sentinel):
        if path is sentinel:
            path = []
        # rest of code
    

    下面是一个简短的演示,演示了可变默认参数的“特殊”行为。您可以看到
    lst
    记住了它以前的内容

    def test(a, lst=[]):
        lst += [a]
        print(a, lst)
    
    for i in range(5):
        test(i)
    
    输出

    0 [0]
    1 [0, 1]
    2 [0, 1, 2]
    3 [0, 1, 2, 3]
    4 [0, 1, 2, 3, 4]
    
    0 [0]
    1 [1]
    2 [2]
    3 [3]
    4 [4]
    
    相反,使用
    lst=lst+[a]
    ,我们创建一个新列表,而不是附加到默认列表

    def test(a, lst=[]):
        lst = lst + [a]
        print(a, lst)
    
    for i in range(5):
        test(i)
    
    输出

    0 [0]
    1 [0, 1]
    2 [0, 1, 2]
    3 [0, 1, 2, 3]
    4 [0, 1, 2, 3, 4]
    
    0 [0]
    1 [1]
    2 [2]
    3 [3]
    4 [4]
    

    节点是什么?您是否收到错误消息或错误结果?它们只是来自[('A','B'),('B','C'),('B','D'),('C','D'),('E','F'),('F','C')]的像'A'和'B'这样的字符。这很好地解释了这一点,非常感谢!因此,那里的路径是局部的,而另外两个路径是全局的,因为它们会影响以前的递归调用?@SandeepChowdary这并不完全是局部/全局问题。默认列表参数的行为类似于函数的静态变量,但如果您不知道其他语言中的静态变量,我想这种解释没有多大帮助。:)因此,我刚刚添加了两个示例,这两个示例应该可以清楚地说明发生了什么。顺便说一句,如果我的答案对你有帮助,请考虑它。@ SaDeTiCoudDaRe>只是用Python,如果使用一个易变的对象,比如<代码> [/C]>作为默认参数,它在程序的开始时被创建一次,然后一次又一次地重复使用。因此,后续调用将看到以前对其进行的任何修改。这是一个有争议的设计,因为它与大多数其他语言相反,最终成为python初学者(以及一些更有经验的开发人员)经常遇到的陷阱。感谢大家对它的解释如此之好!