I've been working on my generator functions and expressions recently, but I'm not quite sure how I would tackle this. How could I use a generator function to yield and then later print the values in order?
I built my BST using pythons list
bst = [20, [10, [5, [2, [], []], [8, [], []]], [15, [], []]], [30, [25, [22, [], []], [27, [], []]], [35, [], [37, [], []]]]]
If I were to print the inorder traversal, I have no problem. So if I were to call inorder(bst)
for the following function:
def inorder(tree):
if tree:
inorder(tree[1])
print (tree[0])
inorder(tree[2])
I get this output.
2
5
8
10
15
20
22
25
27
30
35
37
I would think that a generator expression would be equally as simple
def inorder(tree):
if tree:
inorder(tree[1])
yield (tree[0])
inorder(tree[2])
The problem I'm running into is getting my main to iterate through what's yielded in the function. I thought it was supposed to be something like
test= inorder(bst)
for i in range(0,len(l)): # l is the number of items in bst
print (next(test))
Instead of iterating over the entire functions yields, it simply stops the iterable seemingly before it starts.
20
Traceback (most recent call last):
File "functionGenerator.py", line 64, in <module>
print(next(test))
StopIteration
What do I need to do to make my function generator operate correctly?
Your inorder()
implementation doesn't correctly recurse. You are only printing the current top node of your tree. That's because only calling inorder(tree[1])
or inorder(tree[2])
returns a generator object, you are not iterating over those generators.
Use
def inorder(tree):
if tree:
yield from inorder(tree[1])
yield tree[0]
yield from inorder(tree[2])
The yield from
expression delegates the generator to another, yielding from that sub-generator until it is done. That way you properly recurse.
If you are using an older Python release (before Python 3.3), you need to manually iterate over the recursive calls:
def inorder(tree):
if tree:
for sub in inorder(tree[1]):
yield sub
yield tree[0]
for sub in inorder(tree[2]):
yield sub
Next, you can just iterate over the inorder()
generator:
>>> for node in inorder(bst):
... print(node)
...
2
5
8
10
15
20
22
25
27
30
35
37
although using next()
works too:
>>> tree = inorder(bst)
>>> print(next(tree))
2
>>> print(next(tree))
5
but iteration is cleaner and stops automatically once StopIteration
is raised.