iterable vs iterator
iterable:
1. an object that has an __iter__ method which returns an iterator, or
2. an object that defines a __getitem__ method that can take sequential indexes starting from zero (and raises an IndexError when the indexes are no longer valid)
containers (tuple, list, set, dict, str), file
iterator:
An iterator is an object with a next (Python 2) or __next__ (Python 3) method.
for loop, while, map, list comprehension, counter, itertools, generator function, generator expression
An ITERABLE is:
- anything that can be looped over (i.e. you can loop over a string or file) or
- anything that can appear on the right-side of a for-loop:
for x in iterable: ...
or - anything you can call with
iter()
that will return an ITERATOR: iter(obj)
or - an object that defines
__iter__
that returns a fresh ITERATOR, or it may have a __getitem__
method suitable for indexed lookup.
An ITERATOR is an object:
Notes:
- The
__next__
method in Python 3 is spelt next
in Python 2, and - The builtin function
next()
calls that method on the object passed to it.
Iterators are themselves also iterable, with the distinction that their __iter__()
method returns the same object (self
)
iter(iterable_obj) iterable_obj.__iter__()
next(iterator_obj) iterator_obj.__next__()
A generator, file or database cursor can only be iterated once and thus are their own iterators
So an iterator is a value factory. Each time you ask it for "the next" value, it knows how to compute it because it holds internal state.
There are countless examples of iterators. All of the itertools
functions return iterators. Some produce infinite sequences: Some produce infinite sequences from finite sequences Some produce finite sequences from infinite sequences
Central idea: a lazy factory
From the outside, the iterator is like a lazy factory that is idle until you ask it for a value, which is when it starts to buzz and produce a single value, after which it turns idle again.
NOTE:
Often, for pragmatic reasons, iterable classes will implement both __iter__()
and __next__()
in the same class, and have __iter__()
return self
, which makes the class both an iterable and its own iterator. It is perfectly fine to return a different object as the iterator, though.
make a iterator
very good post!!! (first and second posts)
make an object iterable
following return iterator:
iterator protocol
iter()
generator function and generator expression
itertools