# Python Generators

Generators are objects used to create iterable objects (eg functions) in Python and do not take up any memory space. For example, generating 100,000 values and keeping them in a list will take up a lot of memory. So it would make sense to write a function that performs this operation in the form of a generator function. If you want to understand generators, let’s try to write a function without using generator first.

```
def myMath():
result = []
for i in range(1,6):
result.append(i**2)
return result
print(myMath())
```

[1, 4, 9, 16, 25]

If you want to write this function using a generator. We will use the yield keyword for generators to generate value.

```
def myMath():
result = []
for i in range(1,6):
yield i ** 2
return result
generator= myMath()
print(genarator)
```

<generator object myMath at 0x7f2d4006d570>

In the first function we write, we go from 1 to 6 and assign the square of each value to the result named list and then return this list.

In the second function we wrote with Generator, we think that we generate values with the yield keyword. But in fact, when we call this function, only one generator object is returned to us, and only the values of the generator object are generated one by one. In short, the values are not kept in memory. Let’s try to understand the situation better by creating one iterator on this generator object.

```
def myMath():
result = []
for i in range(1,6):
yield i ** 2
return result
generator = myMath()
iterator = iter(generator)
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
```

1 4 9 16 25

In fact, the generator object only generates values by using the keyword yield when we want to reach values. So generators only work if we want to reach values. That’s exactly the logic of generators! Now let’s try to convert list comprehensions into generators.

```
myList = [i * 3 for i in range(5)]
print(myList)
```

[0, 3, 6, 9, 12]

We use () instead of [] to convert such a list comprehension to the generator object.

```
generator = (i * 3 for i in range(5))
print(generator)
```

<generator object <genexpr> at 0x7f2d2bfd7728>

```
generator = (i * 3 for i in range(5))
iterator = iter(generator)
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
```

0 3 6 9 12

Let’s create another generator function to understand the subject.

```
def theMultiplicationTable():
for i in range(1,11):
for j in range(1,11):
yield "{} x {} = {}".format(i,j,i*j)
for i in theMultiplicationTable():
print(i)
```

1 x 1 = 1 1 x 2 = 2 1 x 3 = 3 1 x 4 = 4 1 x 5 = 5 1 x 6 = 6 1 x 7 = 7 1 x 8 = 8 1 x 9 = 9 1 x 10 = 10 2 x 1 = 2 2 x 2 = 4 2 x 3 = 6 2 x 4 = 8 2 x 5 = 10 2 x 6 = 12 2 x 7 = 14 2 x 8 = 16 2 x 9 = 18 2 x 10 = 20 3 x 1 = 3 3 x 2 = 6 3 x 3 = 9 3 x 4 = 12 3 x 5 = 15 3 x 6 = 18 3 x 7 = 21 3 x 8 = 24 3 x 9 = 27 3 x 10 = 30 4 x 1 = 4 4 x 2 = 8 4 x 3 = 12 4 x 4 = 16 4 x 5 = 20 4 x 6 = 24 4 x 7 = 28 4 x 8 = 32 4 x 9 = 36 4 x 10 = 40 5 x 1 = 5 5 x 2 = 10 5 x 3 = 15 5 x 4 = 20 5 x 5 = 25 5 x 6 = 30 5 x 7 = 35 5 x 8 = 40 5 x 9 = 45 5 x 10 = 50 6 x 1 = 6 6 x 2 = 12 6 x 3 = 18 6 x 4 = 24 6 x 5 = 30 6 x 6 = 36 6 x 7 = 42 6 x 8 = 48 6 x 9 = 54 6 x 10 = 60 7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49 7 x 8 = 56 7 x 9 = 63 7 x 10 = 70 8 x 1 = 8 8 x 2 = 16 8 x 3 = 24 8 x 4 = 32 8 x 5 = 40 8 x 6 = 48 8 x 7 = 56 8 x 8 = 64 8 x 9 = 72 8 x 10 = 80 9 x 1 = 9 9 x 2 = 18 9 x 3 = 27 9 x 4 = 36 9 x 5 = 45 9 x 6 = 54 9 x 7 = 63 9 x 8 = 72 9 x 9 = 81 9 x 10 = 90 10 x 1 = 10 10 x 2 = 20 10 x 3 = 30 10 x 4 = 40 10 x 5 = 50 10 x 6 = 60 10 x 7 = 70 10 x 8 = 80 10 x 9 = 90 10 x 10 = 100