I'm creating a simple tree where each node has any number of children in Python, and I created a Node class to help me. Each node holds a reference to its parent node (int), and any children nodes (list).
However, explicitly adding an empty list to the Node constructor's argument gave me strange results, and I'd love an explanation as to why this behaviour changes when the list is explicit or not explicitly put in the constructor arguments:
Implementation #1:
class Node:
def __init__(self, value, parent, children=[]):
self.parent = parent
self.value = value
self.children = children
Implementation #2:
class Node:
def __init__(self, value, parent):
self.parent = parent
self.value = value
self.children = []
To populate the 'nodes' array:
parents = [4,-1,4,1,1]
nodes = [None] * n
for i in range(n):
nodes[i] = Node(i, parents[i])
To store the parent attribute of each node:
tree = Tree()
for i, node in enumerate(nodes):
parent_id = node.parent
if parent_id == -1:
tree.root = nodes[i]
else:
nodes[parent_id].children.append(node.value)
print([(node.value, node.children) for node in nodes])
With Implementation #1 I get:
[(0, [0, 2, 3, 4]), (1, [0, 2, 3, 4]), (2, [0, 2, 3, 4]), (3, [0, 2, 3, 4]), (4, [0, 2, 3, 4])]
but with Implementation #2 I (correctly) get:
[(0, []), (1, [3, 4]), (2, []), (3, []), (4, [0, 2])]
Why the difference? I don't understand why the list is fully populated for each node even with the if
and else
statements.
All help appreciated, including if you think there are better ways to do this.