Generators in Python
Tags: python, generators, yield, return
Published: 2021-01-24 07:28:46

## Yield
Yield is a keyword in python which is used to throw[return] a single value from a list at a time to a calling function, whenever a function encounters a yield keyword it pauses the execution of the function and throws specified values by maintaining the local memory. 
```python
# Function which yields the numbers.
def normal_yield ():
    yield 1
    yield 2
    yield 3
    
# iterate over the numbers
for value in normal_yield() :
    print (value)
```
Whenever calling function execution stops, then control passes to the next line below the yield keyword in the called function.
```python
# Program to count numbers 1 to 10.
def number_count ():
    # value initialization.
    i = 0
    # infinite loop.
    while True:
        yield i
        # after function called, flow execution starts from here.
        i = i + 1

# Priting the values.
for count in number_count ():
    if count > 10 :
        break
    print (count)
``` 
## Iterators
We can also iterate through the list using the next() iterator function after the list is yielded. Although 'for in' loop is much more convenient than the next() method in case of execution time.
```python
def square_number (nums):
    for i in nums:
        yield (i*i)
 
#variable holding the yielded number
my_nums = square_number ([1,2,3,4,5])

#iterating using the next() functions
print (next(my_nums))
print (next(my_nums))
print (next(my_nums))
print (next(my_nums))
print (next(my_nums))  
```
## Generators
Generators are like the normal python functions which we define, but if the function contains the 'yield' keyword in the definition then the function becomes a generator function. Yield is a keyword that makes the generator function.
```python
def compute ():
    i=0
    while True:
      yield i
      i = i + 1

for check in compute ():
    if check % 2 == 0:
        print(str(check) + " is Even")
    elif check > 10:
        break
```
## Return vs Yield
### 1. Return
Whenever a function runs, the return statement has to wait for the process to complete and after the function execution comes to an end it returns the whole variable or list to the calling function. This takes some time for execution as well as occupies the memory for the whole list. The next time we want to execute the same function then it will run from the beginning.
```python
def square_numbers (nums):
    result = []
    for i in nums:
        result.append (i*i)
    #return has to wait to process the above statements.
    return result
my_number = square_numbers ([1,2,3,4,5])
print (my_number)
```
### 2. Yield
If the function encounters yield keyword it pauses the execution and sends the value to the calling function with keeping local memory as it is, after the calling function executes its task the process returns to the next line of yield in the function definition. With this, the execution speed is maintained as well as it also takes very little space in memory.
```python
def number_square (nums):
    for i in nums:
        yield (i*i)
numbers = number_square ([1,2,3,4,5])
for value in numbers:
    print (value)
```
## Advantages of Generators:
1. Works in a better way with large sets of data as generators 
   throw only one value at a time instead of returning the whole 
   list like a return.
2. Return statement consumes lots of space in memory and also 
   takes more time for execution while generators don't.
3. Return allows the function to execute from the beginning while 
   yield only executes the statement below it and maintains local 
   memory for variables.

## Disadvantage of Generators:
1. The only disadvantage of generators is that they are not 
   commonly used and are less popular.