我想在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")
。为什么会这样?
答案 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
和+
应该具有相同的结果。