Vinny Vinny - 1 year ago 89
Python Question

How an iterable object is iterated without next?

I've done a research over similar questions on this subject, but didn't find a duplicate.

It is stated that an object is iterable if it implements

__iter__
protocol.


iterator.__iter__()
:
Return the iterator object itself. This is required to allow both containers and iterators to be used with the for and in statements.

iterator.__next__()
:
Return the next item from the container. If there are no further items, raise the StopIteration exception.


From my understanding this applies to all iterator objects. I've encountered a code that implements a binary-tree container. The container only has
__iter__
and so does the node objects resides in it.

The
__iter__
implementation of the Node objects returns a generator. It yields objects and seems to do all the logic, without an implementation of
__next__
.

How this code actually works? It seems to function just as a regular iterator, but this one has no
__next__
. Ofcourse if I manually do
iter(obj)
and then
next(obj)
it works. Here is the code snippet:

class BinaryCont(object):

def __init__(self):
self.root = None
self.size = 0

def __iter__(self):

class EmptyIter():
def next(self):
raise StopIteration

if self.root:
return self.root.__iter__()
return EmptyIter()

class Node(object):

def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right

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

yield self.val

if self.has_right_child():
for child in self.right:
yield child


An example of running code

bt = BinaryCont()
bt.insert(5)
bt.insert(3)
bt.insert(7)
for node in bt:
print node

3
5
7

it = iter(bt)
type(it)
<type 'generator'>

Answer Source

Your __iter__ method is a generator function, because it uses yield in the function body. A generator function, when called, returns a generator object. It is that object that has a __next__ method.

Your Node is not an iterator itself. It is merely an iterable object; an iterable object returns a new iterator instance when you call it's __iter__ method, which is what happens here.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download