An object is iterable if it returns an iterator when its __iter__ method is invoked. Iterable values represent data collections, and they provide a fixed representation that may produce more than one iterator.

For example, an instance of the Letters class below represents a sequence of consecutive letters. Each time its __iter__ method is invoked, a new LetterIter instance is constructed, which allows for sequential access to the contents of the sequence.

>>> class Letters:
            def __init__(self, start='a', end='e'):
                self.start = start
                self.end = end
            def __iter__(self):
                return LetterIter(self.start, self.end)
    

The built-in iter function invokes the __iter__ method on its argument. In the sequence of expressions below, two iterators derived from the same iterable sequence independently yield letters in sequence.

>>> b_to_k = Letters('b', 'k')
    >>> first_iterator = b_to_k.__iter__()
    >>> next(first_iterator)
    'b'
    >>> next(first_iterator)
    'c'
    >>> second_iterator = iter(b_to_k)
    >>> second_iterator.__next__()
    'b'
    >>> first_iterator.__next__()
    'd'
    >>> first_iterator.__next__()
    'e'
    >>> second_iterator.__next__()
    'c'
    >>> second_iterator.__next__()
    'd'
    

The iterable Letters instance b_to_k and the LetterIter iterator instances first_iterator and second_iterator are different in that the Letters instance does not change, while the iterator instances do change with each call to next (or equivalently, each invocation of __next__). The iterator tracks progress through sequential data, while an iterable represents the data itself.

Many built-in functions in Python take iterable arguments and return iterators. The map function, for example, takes a function and an iterable. It returns an iterator over the result of applying the function argument to each element in the iterable argument.

>>> caps = map(lambda x: x.upper(), b_to_k)
    >>> next(caps)
    'B'
    >>> next(caps)
    'C'