6

I'm writing a very simple Tree class:

class Tree:
    def __init__(self, value_ = None, children_ = None):
        self.value = value_
        self.children = children_

I'd like to be able to perform both DFS and BFS traversal with a simple loop, i.e.:

t = Tree()
# ...fill tree...

for node in t:
    print(node.value)

In C++, for example, you can have multiple types of iterators - so I could define both a DFS and a BFS iterator and use one or the other depending on what type of traversal I wanted to do. Is this possible to do in Python?

8
  • Tree is not a class. It is a function. Classes are defined like: class Tree(object): Commented May 1, 2016 at 5:02
  • @ozgur: Typo - thanks for catching! Commented May 1, 2016 at 5:03
  • How would you specify which type of iteration you want to do in a particular case? Commented May 1, 2016 at 5:06
  • 1
    @AkshatMahajan: There was a major typo initially (I actually had written def instead of class) - ozgur was right :) Commented May 1, 2016 at 5:08
  • 1
    @tonysdg notice that in your C++ examples, you're constructing new iterators by calling the constructor implicitly. In Python the very same would have to be written it = TreeDFSIterator(tree.begin()) and it = TreeBFSIterator(tree.begin()), and that is also doable. In Python, objects have type, but since names are not objects (unlike in C++), the names themselves do not have types. Commented May 1, 2016 at 5:53

2 Answers 2

9

You can have multiple methods returning iterators and have the 'default' one as __iter__. Below is a simple binary tree where 'default' iterator does DFS and which additionally supports BFS with separate method:

from collections import deque

class Tree(object):
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

    def __iter__(self):
        if self.left:
            for x in self.left:
                yield x

        yield self.value

        if self.right:
            for x in self.right:
                yield x

    def bfs(self):
        q = deque([self])
        while q:
            x = q.popleft()
            if x:
                yield x.value
                q.extend([x.left, x.right])

Short example of usage:

root = Tree(2)
root.left = Tree(1)
root.right = Tree(4)
root.right.left = Tree(3)
root.right.right = Tree(5)

print list(root) # [1, 2, 3, 4, 5]
print list(root.bfs()) # [2, 1, 4, 3, 5]
Sign up to request clarification or add additional context in comments.

Comments

3

You could write separate methods on your class for the two types of iteration. These could for instance be generators that yield values in whatever order you want. You would then write something like:

for node in t.depth_first():
    # ...

for node in t.breadth_first():
    # ...

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.