Function Generators :
A generator is simply a function which returns an object on which we can call next, such that for every call it returns some value, until it raises a StopIteration exception, signaling that all values have been generated. Such an object is called an iterator.
In Simple Terms, Generator functions allow us to write a function that can send back a value and then later resume to pick up where it left off.
Normal functions return a single value using return. However, there is an alternative, called yield Using which anywhere in a function makes it a generator.
Generators are best for calculating large sets of results (particularly in calculations that involve loops themselves) in cases where we don’t want to allocate the memory for all of the results at the same time.
- Advantages of using generator
- Instead of having to compute an entire series of values up front, the generator computes one value and then suspends its activity awaiting the next instruction. This feature is known as state suspension.
- Resulting code is more memory efficient.
Examples : generator which calculate the square of numbers
# Generator function for the square of numbers
def gensquare(n):
for num in range(n):
yield num**2
# calling the generator function directly will provide the Memory location of object.
print(gensquare(5))
# Output :
<generator object gensquare at 0x7f056ea43580>
# If we want to print all the value at once we need to cast it to list.
print(list(gensquare(5)))
# Output :
[0, 1, 4, 9, 16]
# Using for loop to iterate through the generator
for numbers in gensquare(3):
print(numbers)
# Output :
0
1
4
Another Examples : generator which calculates the fibonacci numbers.
def genfibon(n):
"""
Generate a fibonnaci sequence up to n
"""
a = 0
b = 1
for i in range(n):
yield a
a,b = b,a+b
for num in genfibon(6):
print(num)
# Output :
1
1
2
3
5
8
next() :
The next() function allows us to access the next element in a sequence.
def generate_number(n=1):
for x in range(n):
yield x
numbers = generate_number(3)
print(next(numbers)) # Output : 0
print(next(numbers)) # Output : 1
print(next(numbers)) # Output : 2
print(next(numbers)) # Output : Traceback (most recent call last):
File "<string>", line 9, in <module> StopIteration
iter() :
String object supports iteration, but we can not directly iterate over it as we could with a generator function. The iter() function allows us to iterate through a string.
# Iterate over string
str1 = 'Hello'
for letters in str1:
print(letters)
# Output :
H
e
l
l
o
# Iterate over string using next()
next()
# Output :
Traceback (most recent call last):
File "<string>", line 6, in <module> TypeError: 'str' object is not an iterator
We can fix this issue using iter() function.
# Iterate over string using iter() and next()
s_iter = iter(str1)
print(next(s_iter)) # Output : H
print(next(s_iter)) # Output : e
print(next(s_iter)) # Output : l