The yield keyword is fundamental to the creation of generators. Consider the following generator function:

def createGenerator():
    print('Initial call')
    yield '1'
    print('Second call')
    yield '2'

a = createGenerator()

Calling the createGenerator() function will create a generator object stored as a. Note that the code inside the generator function will not be run yet.

print(next(a)) 
# Initial call
# 1

The first time the generator object is iterated over (in a loop or with next()), the function code will be run from the start until the first yield. The value in the yield statement is returned and the current position in the code is saved internally.

print(next(a))
# Second call
# 2

The second next call will resume the code from just after the previous yield and will continue running it until another yield is found where it returns the desired value.

When there are no more yield keywords, the generator object is considered empty.

print(next(a)) # StopIteration error