recursively editing member variable: All instances have same value

169 views Asked by At

I want to create a Tree data structure that consists of TreeNode objects. The root is a TreeNode. Each TreeNode has one parent TreeNode and a list of children TreeNodes. The Tree is built up recursively. I simplified the code to make the example not too difficult. The function get_list_of_values_from_somewhere works correctly. The recursion ends when there are no child_values for a TreeNode and get_list_of_values_from_somewhere returns an empty list. That works perfectly well.

The children member of each TreeNode is not correct. The script collects all the TreeNodes in a list (node_list). There I can check that each TreeNode has a parent node and this parent node is correct.

But for some reason they all have the same list of childrens. I don't understand why. Everything else is correct. The recursion works, the TreeNodes are created correctly, their parent is correct. Why is their children list not filled correctly and how would you edit the memver variables of the instances after creating the instance?

class Tree(object):

    def __init__(self, root_value):
        print ("Creating tree")
        self.root = self.createTree(root_value)
        self.node_list = []

    def createTree(self, value, parent=None):
        node = TreeNode(value, parent)

        children_values = get_list_of_values_from_somewhere()
        for child_value in children_values:
            child_node = self.createTree(child_value, node)
            self.node_list.append(child_node)

            node.children.append(child_node)
            # I also tried alternatives:
            #node.insertChildren(self.createTree(child_value, node))
            #node.insertChild(child_node)

        return node


class TreeNode(object):

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

        self.value = value
        self.parent = parent
        self.children = children

    def insertChildren(self, children=[]):
        self.children += children

    def insertChild(self, child):
        self.children.append(child)


if __name__ == '__main__':
    tree = Tree(1)

    #tree.node_list contains a list of nodes, their parent is correct
    #tree.root.children contains all children
    #tree.node_list[x] contains the same children - although many of them should not even have a single child. Otherwise the recursion would not end.
1

There are 1 answers

0
S.Lott On BEST ANSWER

Be very, very cautious of this:

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

and this:

def insertChildren(self, children=[]):

The initial value -- the list object created by [] -- is a single object which is shared. Widely.

You are using this single, shared, default list object widely.

You may want to use this instead.

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

This technique will create a fresh, empty list object. No sharing.