In this tutorial, we will learn about generators in python,how they are different with iterators and normal functions and use of generators.
As we know to build an iterator we have to use __iter__() and __next__() method.And we also use StopIteration to prevent the function to infinity.
But these methods are bit lengthy.Generator comes here to prevent this and helps to rescue from these situations.
Generators can be defined as a simple way of creating iterators.
Basically, a generator is a function that returns an object(iterator) which we can iterate over.
It is very easy to create generators in python.It is similar to defining a normal function but with a yield statement instead of return statement.
The difference between the yield and return statement is that return statement terminates the entire function in one time while yield statement to return each element one at a time.After running one time, it pauses the function and saves all its states and later continues for next calls.
In ths section we will learn about how generators can be used with loops.
The generator functions are implemented within a lopp under suitable terminating condition.
def rev_list(a=[]):
length = len(a)
for i in range(length - 1, -1, -1):
yield a[i]
# For loop to reverse the string
for word in rev_list(["hello","welcome","to","my","program"]):
print(word)
Output:
program
my
to
welcome
hello
In the above program we used generator that reverses a list and here we used range() function to get the index of the reverse order of the list.
Generators can be easily created by using generator expressions.It makes building generator very easy.
Generator expressions create anonymous generator functions like lambda functions which are used to create anonymous functions.
The syntax for generator expression is similar to that of a list comprehension in Python. But the square brackets are replaced with round parentheses.
Example:# Initialize the list
my_list = [1,5,25,100]
# multiply each term by 2 using list comprehension
list_1 = [var*2 for var in my_list]
# same thing can be done using a generator expression
# generator expressions are surrounded by parenthesis ()
generator_1 = (var*2 for var in my_list)
print(list_1)
print(generator_1)
print(next(generator_1))
print(next(generator_1))
print(next(generator_1))
print(next(generator_1))
Output:
[2, 6, 12, 20]
at 0x7f6a440c7510>
2
6
12
20
As you can see the above code will return a generator object which produces items only on demand.
To produce the result we have to pass the generator in next statement..
Generators can be implemented in very simple and concise way as compared to the iterator.
Let's take an example, we will create a simple program by using iterator as well as generator.
class Multi:
def __init__(self, mix=0):
self.n = 0
self.mix = mix
def __iter__(self):
return self
def __next__(self):
if self.n < self.min:
raise StopIteration
result = 2 * self.n
self.n += 1
return result
Generator example:
def MultiGen(min=0):
n = 0
while n < min:
yield 2 * n
n += 1
A normal function to return a sequence will create the entire sequence in memory before returning the result.
Generator implementation of such sequences is memory friendly and is preferred since it only produces one item at a time.