class Node:
    def __init__(self, value):
        self._value = value
        self._children = []

    def __repr__(self):
        return f'Node({self._value!r})'

    def add_child(self, node):
        self._children.append(node)

    def __iter__(self):
        return iter(self._children)

    def depth_first(self):
        yield self
        for child in self:
            yield from child.depth_first()

    def breadth_first(self):
        queue = [self]
        while queue:
            node = queue.pop(0)
            yield node
            for child in node:
                queue.append(child)

root = Node("root")
child1 = Node("child 1")
child2 = Node("child 2")
root.add_child(child1)
root.add_child(child2)
grandchild1 = Node("grandchild a")
child1.add_child(grandchild1)
grandchild2 = Node("grandchild b")
child1.add_child(grandchild2)

print("Depth first:")
for node in root.depth_first():
    print(node)

print("Breadth first:")
for node in root.breadth_first():
    print(node)