# Python Generators and Iterators

## Iterators

An iterator is an object that contains a countable number of values. In Python, an iterator is an object which implements the iterator protocol, which consists of the methods `__iter__()` and `__next__()`.

### Iterating Through an Iterator

```python
mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)

print(next(myit))
print(next(myit))
print(next(myit))
```

## Generators

Generators are a simple way of creating iterators. A generator is a function that returns an object (iterator) which we can iterate over (one value at a time).

### Creating a Generator

It is fairly simple to create a generator in Python. It is as easy as defining a normal function, but with a `yield` statement instead of a `return` statement.

```python
def my_generator():
    n = 1
    print('This is printed first')
    yield n

    n += 1
    print('This is printed second')
    yield n

    n += 1
    print('This is printed at last')
    yield n

# Using the generator
for item in my_generator():
    print(item)
```

### Generator Expressions

Simple generators can be easily created on the fly using generator expressions. The syntax for generator expression is similar to that of a list comprehension in Python, but the square brackets are replaced with round parentheses.

```python
my_list = [1, 3, 6, 10]

generator = (x**2 for x in my_list)

print(next(generator)) # Output: 1
print(next(generator)) # Output: 9
```

[[programming/python/python]]