1

I am developing a class for creating a Tree object. For some reason when I am establishing parent child relationship between the root and the children nodes, all the nodes are getting their children attributes updated. I am not sure what is causing this. I cannot find any bug in my code. Any guidance and pointers or explanation of the internal workings of my code will be much appreciated.

    class TreeNode(): 
        def __init__(self, val, children=[], parent=None): 
            self.val = val
            self.children = children
            self.parent = parent
    
        def __str__(self) -> str:
            return f"{self.val} with children {[child.val for child in self.children]}  with parent {None if self.parent==None else self.parent.val}"
    
        def add_children(self, children): 
            for child in children:
                assert isinstance(child, TreeNode)
                self.children.append(child)
                child.parent = self 
                
    # create nodes 
    root = TreeNode(0)
    node1 = TreeNode(1)
    node2 = TreeNode(2) 
    node3 = TreeNode(3)
    node4 = TreeNode(4) 
    node5 = TreeNode(5) 
    node7 = TreeNode(7) 
    node6 = TreeNode(6)
    
    print('node4 children', node4.children) # PRINTS: [] # as expected 
    # add children node1 and node2 to root
    root.add_children([node1, node2])
    
    # When I am adding nodes it is adding the same children to all the nodes and updating their children attribute 
    
    print('root', root) # PRINTS: root 0 with children [1, 2]  with parent None
    print('node4', node4) # PRINTS: node4 4 with children [1, 2]  with parent None # How does node4 have children! 
  • Does this answer your question? ["Least Astonishment" and the Mutable Default Argument](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument) (The default for the `children` argument in `TreeNode.__init__` is mutable) – Iain Shelvington Dec 16 '21 at 04:35
  • Yes it does! I was able to fix it with your suggestion; thanks! However, when does `TreeNode.__init__` get called again for the other nodes even tho the children attribute for those nodes are already empty list? – Ahnaf Masroor Dec 16 '21 at 04:45
  • `TreeNode.__init__` is called every time you create an instance of the class (`TreeNode(x)`), because of your mutable default argument `self.children` is referencing the exact same list for every single instance – Iain Shelvington Dec 16 '21 at 04:49
  • Oh I see! `TreeNode.__init__` is not being called. But rather all the children attribute point to the same list and therefore updating one updates all! Thanks a lot. – Ahnaf Masroor Dec 16 '21 at 04:58

0 Answers0