I have a rather complex tree structure that I want to traverse and aggregate values over (e.g. sum, concatenate, append...). I want traverse
to be a method of the tree rather than a separate function. I can traverse and apply a function to each node, but I cannot figure out how to update an aggregation variable associated with the tree.
Here is a simplified version of my code including a node handler with no aggregation, this works.
# A tree is a node that recursively includes more nodes under it.
# More correctly the Tree is the particular node regarded as the root Node.
class Node:
def __init__(self, value):
self.value = value
self.children = []
def traverse(self, handle_node):
handle_node(self)
for child in self.children:
child.traverse(handle_node)
tree = Node('A')
tree.children.append(Node('B')) # Note we append Nodes not values!
tree.children.append(Node('C'))
tree.children[1].children.append(Node('D'))
tree.children[1].children.append(Node('E'))
# This is just an example of a node-handler.
def example_func_on_a_node(node):
print(node.value)
# Execute the node handler on every node in the tree.
tree.traverse(example_func_on_a_node)
As expected this prints
A
B
C
D
E
However, what I want is to aggregate in the general case. If I have a node-handler that returns a value how can I combine the value from each node with the values from all prior nodes to ultimately return the aggregate. The node-handler needs to be a general function that takes a node as it's argument and returns a value.
For example suppose I wanted to concatenate the values in the above simple example. The code should look something like this, but this does not work.
class Node2:
def __init__(self, value):
self.value = value
self.children = []
self.concat = ''
def traverse(self, handle_node):
self.concat += handle_node(self)
for child in self.children:
child.traverse(handle_node)
tree = Node2('A')
tree.children.append(Node2('B')) # Note we append Nodes not values!
tree.children.append(Node2('C'))
tree.children[1].children.append(Node2('D'))
tree.children[1].children.append(Node2('E'))
# This is a node-handler that returns a value I want to aggregate.
def example_func_on_a_node2(node):
return node.value
# Execute the node handler on every node in the tree.
tree.traverse(example_func_on_a_node2)
print(tree.concat)
The answer I get is A
, but what I want is 'ABCDE'
Note I have tried many variations including using static and class methods, and nonlocal variables, but quite possibly used them incorrectly.
I can sort of see what I need but cannot see where to place the aggregation variable so it gets passed around the tree and back to the root node while keeping the node-handler and Node class simple.