Friday, June 19, 2020

Python Generators

Python Generators


Generator


Generators are a simple and powerful tool for creating iterators. Generator functions are a special kind of functions that enable us to declare a function that works similar to an iterator. It can be used in a for-loop. It looks like a regular Python function except that it contains yield expressions for producing a series of values usable in a for-loop or that can be retrieved one at a time with the next() function.

Every time next() is called on a generator, it resumes where it left off. It means a generator function can maintain an internal state every time it is invoked.

for example,

def inverse(message):
    for index in range(len(message)-1, -1, -1):
        yield message[index]
        
for char in inverse('Python'):
  print(char)

#Output
n
o
h
t
y
P

Why generators?


  • We can perform all operations that can be done using a class-based iterator. The reason behind the compactness of a generator is that __iter__() and __next__() methods are produced automatically.
  • One of the most important aspects of generators is that the local variables and execution state are saved implicitly between the calls. This makes the generator functions easy to write and more transparent than using instance variables like self.index and self.data.
  • A generator automatically raises StopIteration, when it is terminated.

All these features make it easier to write iterators than writing a regular Python function.


Generator Expressions



We can sometimes briefly write simple generators as expressions only. The syntax appears to the list comprehensions, except the parenthesis are used in place of square brackets. Generator expressions are particularly in situations where the generator is used immediately by the enclosing function. However, generator expressions may seem compact, but they are less versatile than the full generator definitions. Generator expressions are more memory efficient in comparison to the list comprehensions.

For example,

print(sum(i*i*i for i in range(10))) #sum of cubes

#Output
2025

x = [5, 7, 9]
y = [3, 4, 5]
dp=sum(i*j for i,j in zip(x,y))
print(dp)

#Output
88

print(max(i for i in [10,7,9,5,12,14])) 

#output
14