# Iterators - Fri, Oct 4

## Iterators

A container can provide an iterator that provides access to its elements in order

• `iter(iterable)`: return an iterator over the elements of an iterable value
• `next(iterator)`: return the next element in an iterator

## For Statements (Continued)

``````>>> d = {'one': 1, 'two': 2}
>>> v = iter(d.values())
>>> next(v)
1
>>> for something in v:
...    print(something)
...
2
>>> for something in d.values():
...    print(something)
...
1
2
>>> for something in d.values():
...    print(something)
...
1
2``````

## Built-in Iterator Functions

Many built-in Python sequence operations return iterators that compute results lazily. Computations are only performed if you're sure that something else is going to use that result.

• `map(func, iterable)`: iterate over `func(x)` for `x` in `iterable`
• `filter(func, iterable)`: iterate over `x` in `iterable` if `func(x)`
• `zip(first_iter, second_iter)`: iterate over co-indexed `(x, y)` pairs
• `reversed(sequence)`: iterate over `x` in a `sequence` in reversed order

To view the contents of an iterator, place the resulting elements into a container.

• `list(iterable)`: create a list containing all `x` in `iterable`
• `tuple(iterable)`: create a tuple containing all `x` in `iterable`
• `sorted(iterable)`: create a sorted list containing all `x` in `iterable`

## Generators

Generators are ways to build arbitrarily complicated iterators.

``````def plus_minus(x):
yield x
yield -x``````

## Generators can Yield from Iterators

A `yield from` statement yields all values from an iterator or iterable.

``````# Python < 3.3
def a_then_b(a, b):
for x in a:
yield x
for x in b:
yield x``````
``````# Python >= 3.3
def a_then_b(a, b):
yield from a
yield from b``````