|
Data Structures and Algorithms
with Object-Oriented Design Patterns in Python |
As discussed in Section
,
the __iter__ method of a Container
returns an Iterator.
In Python, an iterator is implicitly used when you write a for loop
like this:
stack = new StackAsArray(57)
stack.push(3)
stack.push(1)
stack.push(4)
for obj in stack:
print obj
The Python for loop given above
is implemented as if it was coded like this:
it = iter(stack) # Equivalent to stack.__iter__()
while true:
try:
obj = it.next()
print obj
except StopIteration:
break
This code creates an instance of the StackAsArray class
and assigns it to the variable stack.
Next, several ints are pushed onto the stack.
Finally, an iterator is used to systematically print out all
of the objects in the stack.
Program
defines the __iter__ method
of the StackAsArray class.
The __iter__ method returns a new instance
of the nested class StackAsArray.Iterator
that implements the iterator protocol (lines 3-14).

Program: StackAsArray class __iter__ method.
The Iterator class has two instance attributes, _container and _position. The _container instance attribute refers to the stack whose elements are being enumerated. The _position instance attribute is used to keep track of the position in the array of the current object.
The _next method is called in the body of the loop to advance the iterator to the next object in the stack. The _next method increments the _position instance attribute and then returns the object in the stack specified at that position. The _next method resets the position to -1 and raises a StopIteration exception when there are not more elements. Clearly, the running time of _next is O(1).