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?
A single class definition can be used to create multiple objects. As mentioned before, objects are independent.
Technically, in Python, an iterator is an object which implements the iterator protocol, which consist of the methods __iter__() and __next__() .
The __iter__() function returns an iterator for the given object (array, set, tuple, etc. or custom objects). It creates an object that can be accessed one element at a time using __next__() function, which generally comes in handy when dealing with loops.
Here is a list of the differences between Iterable and Iterator in Python. An Iterable is basically an object that any user can iterate over. An Iterator is also an object that helps a user in iterating over another object (that is iterable). We can generate an iterator when we pass the object to the iter() method.
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]
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():
# ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With