I know what's iterator, what's generator, what's iteration protocol, how to create both.
What's an iterator?
Per the glossary, an iterator is "an object representing a stream of data". It has an __iter__() method returns itself, and it has a next() method (which is __next__() in Python 3). The next-method is responsible for returning a value, advancing the iterator, and raising StopIteration when done.
What is a generator?
A generator is a regular Python function containing yield
. When called it returns a generator-iterator (one of the many kinds of iterator).
Examples of how to create generators and iterators
Generator example:
>>> def f(x): # "f" is a generator
yield x
yield x**2
yield x**3
>>> g = f(10) # calling "f" returns a generator-iterator
>>> type(f) # "f" is a regular python function with "yield"
<type 'function'>
>>> type(g)
<type 'generator'>
>>> next(g) # next() gets a value from the generator-iterator
10
>>> next(g)
100
>>> next(g)
1000
>>> next(g) # iterators signal that they are done with an Exception
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
next(g)
StopIteration
>>> dir(g) # generator-iterators have next() and \__iter__
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
Iterator using a class:
>>> class Powers: # "Powers" is a class
def __init__(self, base):
self.base = base
self.exp = 0
def __iter__(self):
return self
def next(self):
self.exp += 1
if self.exp > 3:
raise StopIteration
return self.base ** self.exp
>>> g = Powers(10) # calling "Powers" returns an iterator
>>> type(Powers) # "Power" is a regular python class
<type 'classobj'>
>>> type(g) # "g" is a iterator instance with next() and __iter__()
<type 'instance'>
>>> next(g) # next() gets a value from the iterator
10
>>> next(g)
100
>>> next(g)
1000
>>> next(g) # iterators signal that they are done with an Exception
Traceback (most recent call last):
File "<pyshell#34>", line 1, in <module>
next(g)
StopIteration
Iterator from a sequence example:
>>> s = 'cat'
>>> it = iter(s) # creates an "iterator" from a sequence
>>> type(s) # "s" is a string which is "iterable"
<type 'str'>
>>> type(it) # An "iterator" with next() and __iter__()
<type 'iterator'>
>>> next(it)
'c'
>>> next(it)
'a'
>>> next(it)
't'
>>> next(it)
Traceback (most recent call last):
File "<pyshell#43>", line 1, in <module>
next(it)
StopIteration
Comparison and conclusion
An iterator is an object representing a stream of data. It has an __iter__() method and a next() method.
There are several ways to make an iterator:
1) Call a generator (a regular python function that uses yield
)
2) Instantiate a class that has an __iter__() method and a next() method.
From this, you can see that a generator is just one of many ways to make an iterator (there are other ways as well: itertools, iter() on a regular function and a sentinel, etc).