在Python中,为什么.append与使用+给出不同的结果?

时间:2019-09-02 06:30:56

标签: python tree append

我想在Python中实现一个非常简单的树数据结构。 我想这样做,以便每次添加新节点并指定其父节点时,它都会自动添加到其父节点的children属性中。

我有两种不同的处理方式,一种有效,一种无效,但我不明白为什么。

class Node():
    def __init__(self, value, parent = None, children = []):
        self.value = value          #This is for us to see the name
        self.parent = parent        #Parent node
        self.children = children    #List of child nodes

        #Set this Node as a children of its own parent
        if not parent == None:
            #self.parent.children.append(self)  <--- wrong code
            self.parent.children = self.parent.children + [self]

    def __repr__(self):
        return str(self.value)

tree    = Node("tree")
branch1 = Node("branch1", parent = tree)
branch2 = Node("branch2", parent = tree)
leaf    = Node("leaf", parent = branch1)

这是我按原样获得的代码,以及如果用注释行替换__init__的最后一行所得到的结果。

print(tree.children)
#[branch1, branch2]        <--- expected
#[branch1, branch2, leaf]  <--- with wrong code

print(branch1.children)
#[leaf]                    <--- expected
#[branch1, branch2, leaf]  <--- with wrong code

使用.append方法不仅将节点添加到其父级列表children中,而且还添加到每个节点。即使我定义了一个与其他人完全分离的新Node("other")。为什么会这样?

1 个答案:

答案 0 :(得分:2)

问题在于使用可变的默认值:

def __init__(self, value, parent = None, children = []):

在定义函数后,仅一次创建空列表[],并且所有调用共享同一列表!这就是为什么append对一个孩子列表进行修改的原因-因为他们所有都是一个相同的列表对象。当您使用+追加到列表时,您会遇到上述错误,因为您每次都会重新创建列表,从而取消共享子对象。

正确的解决方案是将children=[]替换为以下内容:

def __init__(self, value, parent=None, children=None):
    if children is None:
        children = []

这将确保为孩子创建一个新列表,然后append+应该具有相同的结果。