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.



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