Previous Lesson | Table of Contents | Next Lesson |

Once you begin using loops, you might notice that you are writing the same types of iterators (the object being iterated over) again and again. For example, you might have:

```
for i in [2, 4, 6, 8, 10, 12]:
print(i)
```

Later on, you have the following code:

```
for i in [3, 6, 9, 12, 15, 18]:
print(i)
```

These iterators look different, but in fact, they are both doing the same thing:
iterating over the first six multiple of a number: `2`

in the first snippet,
`3`

in the second snippet.

Given the similar structure, this suggests that we could create a function that creates these loops, or iterators, for us. This is where generators come in:

```
def f(n):
for i in [1, 2, 3, 4, 5, 6]:
yield i * n
```

We can then rewrite our code as follows:

```
for i in f(2):
print(i)
```

And for the second snippet:

```
for i in f(3):
print(i)
```

These iterators are a lot more compact! The keyword is the **yield** statement,
which turns the function into a generator.

Another advantage of generators is that they only “generate” the next value
**on demand**. Notice for example that in order to iterate over the list
`[1, 2, 3, 4, 5, 6]`

, we have to create the entire list before we can iterate.
To create this list, we need space to store the list. Imagine that we instead
had a billion numbers in our list. That would be enormous!

For a generator, each time we iterate over the loop, the generator gives us
the next value in the generator. Thus, the only space we need is for storing
the generated value and **NOT** the entire sequence of values.

In fact, we could have even simplified our implementation of `f`

as follows:

```
def f(n):
for i in range(1, 7):
yield i * n
```

The **range** function is a builtin function and is itself a generator that
accepts two parameters, `start`

and `end`

, and generates values from `start`

to `end - 1`

. If `end`

is not provided, we assume the generator is from
`0`

to `start - 1`

.

That’s it for now! Let’s practice what we have learned so far:

Create a generator of numbers from

`5`

to`10`

. Iterate over it to print each value divided by 10. (solution)Create a function that creates a generator for the first

`n`

squares (i.e.`1 = 1 * 1`

,`4 = 2 * 2`

,…,`n^2 = n * n`

etc.) (solution).

It should be noted that there are other ways to create generators, but functions are the standard way to do it.

Do generators make sense to you? Then move on to the next lesson.