python iterator and iterable iterator generator

According to python offical docunments, the iterator is ‘an object representing a stream of data’, whileas the iterable is ‘an object capable of returnig its members one at a time’. Moreover, there is the generator which is a special iterator.

If you are confused with all the above, don’t worry, I will explain it thorough enough with solid examples later.

All sequence types are iterables, such as list, str, tuple. So each object you defined with an __iter__() or __getitem__() method (which implements sequence semantics) is an iterable.
Also, some non-sequence types are iterable., such as dict, which includes iterator function dict.items(), dict.keys() etc.

NOTE:
The important thing is the iterable will return an iterator when you call iter(iterable_name) or use it in for-loop. More often, we use it in a for loop and places where a sequence is needed.

iterator

An iterator should comply with the iterator protocol, which is composed with two methods ———— __iter__() and __next()__.
__iter__() returns the iterator object itself.
__next()__ returns the next item from the container. If there are no further items, it should raise the StopIteration exception.
So when you implement an iterator object by define a class, you are required to satisfy all the requirements.

For example:

class (object):
def __init__(self, maxL):
self.maxL = maxL

def __iter__(self):
self.a = 0
return self

def __next__(self):
b = a+1
if b > self.maxL:
raise StopIteration
return b

NOTE:
The iterator will return an iterator itself when you call __iter__() on it. Hence, an iterator is also an iterable. Thus, you can use it just like an iterable. And you can detect that a value is an iterator(instead of a container) if calling iter on it twice produces the same result.
This is a smart and tricky operation, while the other programming languages like C++ usually don’t do that.
Generally, an iterator couldn’t return itself in other programming languages.

generator

Essentially, the generator is just a convienience way of iterator. You don’t have to create a class which should comply with the iterator protocol, since the generator has helped you create them when you write the yield statement.
According the official document:
‘Anything that can be done with generators can also be done with class-based iterators as described in the previous section. What makes generators so compact is that the iter() and next() methods are created automatically.
Another key feature is that the local variables and execution state are automatically saved between calls. This made the function easier to write and much more clear than an approach using instance variables like self.index and self.data.
In addition to automatic method creation and saving program state, when generators terminate, they automatically raise StopIteration. In combination, these features make it easy to create iterators with no more effort than writing a regular function.

NOTE:
The best benefit for the generator is the lazy concept. It only call and run the function when needed, so it saves the memory and make the calculation is more efficent.

“Updating at any time”