0

I have a problem in which I am trying to construct a tree (not always binary). Given a node at any depth of the tree, I wish to be able to add N new nodes to a children list attribute. The following example code results in child nodes being recursivley generated and each new child node in self.children contains a copy of itself.

class Node:

    # Constructor to create a Node
    def __init__(self, data, children=[]):
        self.value = data
        self.children = children

    @classmethod
    def spawn(cls, data):
        return cls(data)

    def spawn_child(self, data):
        child = self.spawn(data)
        self.children.append(child)


def max_depth(node):
    if len(node.children) == 0:
        return 0
    else:
        depths = []
        for child in node.children:
            depths.append(max_depth(child))
        return np.max(depths)+1


if __name__ == '__main__':
    """ Let us create following example tree
         50
        / \
        30   70
     """

    root = Node(50)
    root.spawn_child(30)
    root.spawn_child(70)
    print(max_depth(root))  # results in RecursionError 

Upon checking the max_depth of the tree here we get an error. We have infact created the tree,

         50
        / \
        30    70
       / \   / \
      30 70  30  70
      /   \  /   \
      30  70 30  70
     /     \ /    \
     .     . .     .
     .     . .     .
     .     . .     .

Upon removing the keyword argument children=[] and rewritting the constructor as,

class Node:

    # Constructor to create a Node
    def __init__(self, data):
        self.value = data
        self.children = []

we stop the recursive generation of child nodes and generate the correct tree i.e. one root node with a value of 50 which has two children (30 and 70). Now the correct value of max_depth() is printed as 1.

How does including the children attribute as a default keyword with a value corrosponding to an empty list cause this behaviour?

Kyle
  • 115
  • 7
  • It probably is me, but I don't understand anything of this code. Sometimes `point` or `points` is a value, sometimes it is an index, ... very confusing. I gave up. – trincot Jul 31 '22 at 13:02
  • @trincot `point` is the value which corrosponds to each of the unique elements in each sublist (`members_snapshot`) in the `members_list`. `points` corrosponds to the indexes in `members_snapshot` which are equal to that unique value. So `unique_points = [1, 0]`, which is then iterated over and the indexes where `members_snapshot` equal that unique index is stored in `points`. So `points = [0, 1]` and `[2, 3]` i.e. the elements where `members_snapshot` equal 0 and 1 respectivley – Kyle Jul 31 '22 at 13:10
  • Well, I just don't understand the code. Can you edit your question and give a few non-trivial examples of input and the graph you want to get from it (as a drawing or as a JSON structure)? Maybe that will clarify the logic you have in mind. – trincot Jul 31 '22 at 13:19
  • @trincot I have simplified the example a bit. I have found the cause of the issue but do not understand why it exists. – Kyle Jul 31 '22 at 18:23
  • 1
    Thanks. You fell for a trap that is specific for Python: your code uses a default value for a parameter that is mutated (`children`). See duplicate reference. – trincot Jul 31 '22 at 18:28

0 Answers0