创建树时Python中的对象引用问题

创建树时Python中的对象引用问题,python,python-3.x,tree,Python,Python 3.x,Tree,我试图从python中的列表构造一棵树。“我的树”中的节点具有“我的列表”的索引值,每个节点的父节点将是列表中该索引处指定的节点。 在下面的代码示例中,varlist将树的节点元素与输入数组中的值一起存储。 例如,[-1,0,4,0,3]的输入列表应给出以下树: 0 / \ 1 3 \ 4 \ 2 我得到的输出是: 0 None [<__main__.Node1 object at 0x1041051d0>, <__ma

我试图从python中的列表构造一棵树。“我的树”中的节点具有“我的列表”的索引值,每个节点的父节点将是列表中该索引处指定的节点。
在下面的代码示例中,
varlist
将树的节点元素与输入
数组中的值一起存储。
例如,[-1,0,4,0,3]的输入列表应给出以下树:

0 / \ 1 3 \ 4 \ 2 我得到的输出是:

0 None [<__main__.Node1 object at 0x1041051d0>, <__main__.Node1 object at 0x104105208>, <__main__.Node1 object at 0x104105780>, <__main__.Node1 object at 0x104105cc0>]
1 0 [<__main__.Node1 object at 0x1041051d0>, <__main__.Node1 object at 0x104105208>, <__main__.Node1 object at 0x104105780>, <__main__.Node1 object at 0x104105cc0>]
2 4 [<__main__.Node1 object at 0x1041051d0>, <__main__.Node1 object at 0x104105208>, <__main__.Node1 object at 0x104105780>, <__main__.Node1 object at 0x104105cc0>]
3 0 [<__main__.Node1 object at 0x1041051d0>, <__main__.Node1 object at 0x104105208>, <__main__.Node1 object at 0x104105780>, <__main__.Node1 object at 0x104105cc0>]
4 3 [<__main__.Node1 object at 0x1041051d0>, <__main__.Node1 object at 0x104105208>, <__main__.Node1 object at 0x104105780>, <__main__.Node1 object at 0x104105cc0>]
0无[,]
1 0 [, , ]
2 4 [, , ]
3 0 [, , ]
4 3 [, , ]

输出不是我所期望的,因为不知何故,所有节点的
子节点
列表中有4个元素,而我期望其中2个节点有2个子节点,其余为空。有人能帮我解释一下这里发生了什么事吗?

首先,你需要知道
\uuuu repr\uuuu
\uu str\uuuu
之间的区别。在这种情况下,您需要尝试表示您创建的
Node1
对象,因为repr的目标是对象的完整字符串表示;而str只返回一个字符串进行打印。实际上,您应该定义
\uuu repr\uu
。在您的例子中,实际上根本没有使用您实现的函数

另一件事是,永远不要将可变对象用作python函数中的默认参数,这实际上是一种糟糕的做法,如下所示:

将可变列表或字典作为默认参数传递给函数可能会产生不可预见的后果。通常,当程序员使用列表或字典作为函数的默认参数时,程序员希望程序在每次调用函数时创建一个新的列表或字典。然而,Python并不是这样做的。第一次调用函数时,Python会为列表或字典创建一个持久对象。以后每次调用该函数时,Python都会使用从第一次调用该函数时创建的相同持久对象

通常,最佳做法是使用sentinel值表示空列表或字典:

class Node1:
    def __init__(self, val, parent=None, child=None): # default argument should be immutable
        self.val = val
        self.children= []
        if parent and parent.val != -1:
            self.parent = parent
        else:
            self.parent = None
        if child:
            self.children.append(child)

#    def __str__(self):
#        return(str(self.val))

    def __repr__(self):
        return(str(self.val)) # need to define __repr__

def treeHeight(arr): # array is reverse attribute in python, use arr instead
    varlist = []
    for i in range(len(arr)):
        varlist.append(Node1(i))
    for i in range(len(varlist)):
        if arr[i]!=-1:
            varlist[i].parent = varlist[arr[i]]
            varlist[arr[i]].children.append(varlist[i])
        else:
            root = varlist[i]

    for i in range(len(arr)):
        print(varlist[i].val,varlist[i].parent, varlist[i].children)
    return

if __name__ == '__main__':
    print('\n\n')
    treeHeight([-1, 0, 4, 0, 3])

您在
\uuuu init\uuuu
中有一个可变的默认参数。非常感谢!这真的很有帮助。我会记住不可变参数规则。@Kamal,我很高兴它有帮助。为了解决这个问题,最好的做法是使用sentinel值来表示空列表或字典。
class Node1:
    def __init__(self, val, parent, children = ()): # default argument should be immutable
        self.val = val
        if parent == -1:
            self.parent = None
        else:
            self.parent = parent
        if not isinstance(children, list):
            children = list(children)
        self.children = children
    def __str__(self):
        return(str(self.val))

    def __repr__(self):
        return(str(self.val)) # need to define __repr__

def treeHeight(array):
    varlist = [0] * len(array)
    for i in range(len(array)):
        varlist[i] = Node1(i, None)
    for i in range(len(varlist)):
        if array[i] != -1:
            varlist[i].parent = varlist[array[i]]
            varlist[array[i]].children.append(varlist[i])
        else:
            root = varlist[i]
    for i in range(len(array)):
        print(varlist[i].val,varlist[i].parent, varlist[i].children)
    return(None)
if __name__ == '__main__':
    print('\n\n')
    print(treeHeight([-1, 0, 4, 0, 3]))
class Node1:
    def __init__(self, val, parent=None, child=None): # default argument should be immutable
        self.val = val
        self.children= []
        if parent and parent.val != -1:
            self.parent = parent
        else:
            self.parent = None
        if child:
            self.children.append(child)

#    def __str__(self):
#        return(str(self.val))

    def __repr__(self):
        return(str(self.val)) # need to define __repr__

def treeHeight(arr): # array is reverse attribute in python, use arr instead
    varlist = []
    for i in range(len(arr)):
        varlist.append(Node1(i))
    for i in range(len(varlist)):
        if arr[i]!=-1:
            varlist[i].parent = varlist[arr[i]]
            varlist[arr[i]].children.append(varlist[i])
        else:
            root = varlist[i]

    for i in range(len(arr)):
        print(varlist[i].val,varlist[i].parent, varlist[i].children)
    return

if __name__ == '__main__':
    print('\n\n')
    treeHeight([-1, 0, 4, 0, 3])