Generators in Python
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.
# 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.
# 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)
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.
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 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.
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
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.
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)
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.
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:
- 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.
- Return statement consumes lots of space in memory and also takes more time for execution while generators don't.
- 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:
- The only disadvantage of generators is that they are not commonly used and are less popular.
[This article has been contributed by Mr Aniket, Thanks Mr. Aniket 🤗]