Since the yield keyword is only used with generators, it makes sense to recall the concept of generators first and before generators come iterables.

Iterables

Everything one can use for… in… on is an iterable; lists, strings, files. These iterables are handy because someone can read them really easy, but all the values can be stored in memory and this is not always what the programmer wants when he has a lot of values.

list_one = [1, 2, 3] 
for element in list_one:
  print(element)
1
2
3
list_two = [2**x for x in range()]
for element in list_two:
  print(element)
1
2
4

Generators

Generators are iterators, a kind of iterable someone can only iterate over once. Generators do not store all the values in memory, they generate the values on the fly.

the_generator = (x*x for x in range(3))
for element in the_generator:
  print(element)
0
1
4
one_generator = (x+x for x in range(3))
for element in one_generator:
  print(element)
0
2
4

As easy as list comprehensions, except the () instead of []. But, the computer scientist cannot perform for the element in one_generator a second time since generators can only be used once: they calculate 0, then forget about it then calculate 2, and end calculating 4, one by one.
Iterating over the list and the generator looks completely the same. However, although the generator is iterable, it is not a collection, and thus has no length. Collections (lists, tuples, sets) keep all values in memory and anyone can access them whenever needed. A generator calculates the values on the fly and thinks no more of them, so it does not have an overview of the own result set. Generators are especially useful for memory-intensive tasks, where there is no need to keep all of the elements in memory.

Yield

yield is a keyword that is used like return, except the function will return a generator.

def fibonacci(n):
     prev, current = 0, 1    
     counter = 0
     while counter < n:
         yield current
         prev, current = current, prev + current
         counter += 1
fibo = fibonacci(7)
print(fibo)
<generator object fibonacci at 0x7f537ae0ea40>
for element in fibo:
     print(element)
1
1
2
3
5
8
13

When the program calls the function, the code he has written in the function body does not run. The function only returns generator object fibonacci at 0x7f537ae0ea40 . Then, the code will be run each time for uses the generator.
The first time the for calls the generator object created from the function Fibonacci, it will run the code in the function from the beginning until it hits yield, then it will return the first value of the loop which is 1. Then, each other call will run the loop that has been written in the function one more time, and return the next value, until there is no value to return.
The generator is considered empty once the function runs, but does not hit yield anymore. It can be because the loop had come to an end in which the counter reaches the value of n.

For more information check these two links PEP-255, Yield.

If you love writing like me and you want to make extra money check out this link, if you don’t like money forget it my friend.

Cheers,
Zaid Alissa Almaliki