Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Iterator Special Method Names

An iterator is the object responsible for controlling iteration through a collection of objects or range of values. The for statement works by calling the next method of an iterator until the iterator raises an exception. The yield statement makes a function (or method) into an iterator by implicitly creating an object with a next method. We looked at this closely in Chapter 18, Generators and the yield Statement . The techniques there (principally, using the yield statement) are somewhat simpler than creating an explicit iterator object.

Generally, we provide a sequence object to the for statement. The sequence object responds to the for statement's request by creating the required iterator. Clearly, a statement like for var in object statement evaluates the object (.iter) method function to get the necessary iterator object.

The built-in sequence types (list, tuple, string) all produce iterator objects for use by the for statement. The set and frozenset classes also produces an iterator. In the case of a mapping, there are several choices for the target of the iteration: the iterator could iterate over the keys, the values or the items (which are ( key , value ) pairs).

In addition to defining ordinary generator methods by using the yield statement, your classes can also produce iterator objects. This can make a program slightly simpler to read by assuring that loops are simple, obvious for statements.

Creating an Iterator. Generally, an iterator is an object that helps a program with with a more complex container. Consequently, the container will often contain a factory method which creates iterators. The special method __iter__ usually handles this in a container. The for statement uses the iter built-in function. The iter function looks for the __iter__ method.

An iterator object is created by a collection object when requested by the for statement. To make your collection play well with the for statement, implement the following method.

__iter__ ( self ) → Iterator

Returns an iterator in response to the iter function. The iter function is implicitly evaluated by a for statement.

An iterator controls the operation of the for statement, so it is clearly stateful. In addition to at least one internal variable, an iterator is usually created with a reference to the more complex object with which it works.

When we evaluate iter( someList ), we get an iterator object ready to be used with a for statement. The iter function uses __iter__ method function of someList. The __iter__ function creates the object to be used as an iterator.

A complex object will usually provide it's self variable to each iterator that it creates.

Methods of an Iterator. An iterator object has a simple interface definition: it provides a next method, which either returns the next value or raises the StopIteration exception. Further, an iterator needs an __init__ method which will accept the complex object over which the iterator works, and allows the iterator to create appropriate initial values.

__init__ ( self , complexObject )

This will initialize the iterator. Generally, a complex object will create an iterator from it's own __iter__ method, providing it's self variable as the argument. It will do something like this: return MyIterator( self ).

next( self ) → Object

This will advance the iterator to the next value or element. If there is no next value, it will raise the StopIteration exception. If there is a next value, it will return this value.

There's little more than these two methods to an iterator. Often an iterator will also provide a definition of the __iter__ special method name. This will simply return the iterator. This prevents small problems with redundant calls to the iter built-in function.

Example: Non-Zero Iterator. In the following example classes, we'll create a class which wraps a list and provides and a specialized iterator that yields only non-zero values of the collection.

class DataSamples( object ):
    def __init__( self, aList=None ):
        self.values= aList or []
    def __iter__( self ):
        return NonZeroIter( self )
    def __len__( self ):
        return len( self.values )
    def __getitem__( self, index ):
        return self.values[index]
1

When we initialize a DataSamples instance, we save any provided sequence of values. This class behaves like a collection. We haven't provided all of the methods, however, in order to keep the example short. Clearly, to be list-like, we'll need to provide an append method.

2

When we evaluate the iter function for a DataSamples object, the DataSamples object will create a new, initialized NonZeroIter. Note that we provide the DataSamples object to the new NonZeroIter, this allows the iterator to process the collection properly.

class NonZeroIter( object ):
    def __init__( self, aDataSamples ):
        self.ds= aDataSamples
        self.pos= -1
    def next( self ):
        while self.pos+1 != len(self.ds) and self.ds[self.pos+1] == 0:
            self.pos += 1
        if self.pos+1 == len( self.ds ):
            raise StopIteration
        self.pos += 1
        return self.ds[self.pos]
    def __iter__( self ):
        return self
1

When initialized, the NonZeroIter saves the collection that it works with. It also sets it's current state; in this instance, we have pos set to -1, just prior to the element we'll return.

2

The next function of the iterator locates the next non-zero value. If there is no next value or no next non-zero value, it raises StopIteration to notify the for statement. Otherwise, it returns the next non-zero value. It updates its state to reflect the value just returned.

3

The __iter__ function of the iterator typically returns self.

We can make use of this iterator as follows.

ds = DataSamples( [0,1,2,0,3,0] )
for value in ds:
    print value

The for statement calls iter(ds) implicitly, which calls ds.__iter__(), which creates the NonZeroIter instance. The for statement then calls the next method of this iterator object to get the non-zero values from the DataSamples object. When the iterator finally raises the StopIteration exception, the for statement finishes normally.


 
 
  Published under the terms of the Open Publication License Design by Interspire