Several built-in functions take as arguments iterable values and return iterators. These functions are used extensively for lazy sequence processing.

The map function is lazy: calling it does not perform the computation required to compute elements of its result. Instead, an iterator object is created that can return results if queried using next. We can observe this fact in the following example, in which the call to print is delayed until the corresponding element is requested from the doubled iterator.

>>> def double_and_print(x):
            print('***', x, '=>', 2*x, '***')
            return 2*x
    >>> s = range(3, 7)
    >>> doubled = map(double_and_print, s)  # double_and_print not yet called
    >>> next(doubled)                       # double_and_print called once
    *** 3 => 6 ***
    6
    >>> next(doubled)                       # double_and_print called again
    *** 4 => 8 ***
    8
    >>> list(doubled)                       # double_and_print called twice more
    *** 5 => 10 ***
    *** 6 => 12 ***
    [10, 12]
    

The filter function returns an iterator over, zip, and reversed functions also return iterators.

TODO demonstrate these values