Iterators and Generators in Python

Iterators

Iterators

Overview

iterate means to repeat something several times
exactly what we've done in loops.
We can iterate over objects, too. If we implement the __iter__ method.
What an iter method should do, is defined in "The Iterator Protocol" - a concept, present in most modern programming languages.

iterable and the __iter__ method

an object, implementing the __iter__ method is called itarable
The __iter__ method returns an iterator.
iterator is any object with a method called __next__, which is callable without any arguments.
The iterator protocol is changed a bit in Python 3. In the old protocol, iterator objects should have a method called next rather than __next__

iterator and __next__ method

an object, implementing the __next__ method is called iterator
When __next__ method is called, the iterator should return its "next value".
If the iterator has no more values to return, it should raise a StopIteration exception
There is a built-in function called next, wrapping around __next__ that you can use for convenience.
next(it) is equivalent to it.__next__()

Get iterator from iterable

The built-in function iter() can be used to get an iterator from an iterable object.

			iterable = [1,2,3]
			iterator = iter(iterable)


			print( next(iterator) )
			print( next(iterator) )
			print( next(iterator) )

			#1
			#2
			#3
		

Example


			class Fibs:
			  def __init__(self, limit):
			    self.a = 0
			    self.b = 1
			    self.limit = limit
			  def __next__(self):
			    self.a, self.b = self.b, self.a + self.b
			    if ( self.a < self.limit):
			      return self.a
			    else:
			      raise StopIteration
			  def __iter__(self):
			    return self

			fib_numbers = FibsIterable(30)

			for i in fib_numbers:
			  print( i )
		

Resources

Iterator Types @Python3 docs

Generators

Generators

Overview

A generator is a kind of iterator that is defined with normal function syntax
Or more formally: a Python generator is a function which returns a generator iterator by calling yield
Any function that contains a yield statement can be called a generator!

Making a Generator

Creating generator is like creating a normal function, but using yield instead of return
Once the function yields, the function is paused and the control is transferred to the caller.

			def simple_generator():
			  yield 1
		

Example - even numbers generator


			#define the generator function:
			def numbers_generator(start,end):
			  num  = start
			  while num<=end:
			  	# yield is almost like return, but it freezes the execution
			  	yield num
			  	num += 1
			 
			my_numbers = numbers_generator(1,10)
			# iterate over our generator:
			for i in my_numbers:
				print(i)
			

Example - nested list flatten generator


			nested = [[1, 2], [3, 4], [5]]

			def flatten(nested):
			  for sublist in nested:
			    for element in sublist:
			      yield element

			print( list(flatten(nested)) )
		

Resources

Generators @python wiki

Exercises

Task1: Even Numbers generator

The Task

Write a generator function, such that will yield an even number in pre-given interval

			def even_numbers_generator(start,end):
			  # write your code here
			 
			for i in even_numbers_generator(1,10):
				print(i)

			### expected result
			#2
			#4
			#6
			#8
			#10
		

Cyrillic letter generator

The Task

Define a generator function which will yield a Cyrillic letter, starting from 'А', to 'Я'
You can get a letter form its code, using the chr() built-in function, as shown in next example

			print( chr(1040) )
			# 'А''

			print( chr(1041) )
			# 'Б'

			print( chr(1070) )
			# 'Ю'
			print( chr(1071) )
			# 'Я'
		

Submission

PLease, prefix your filenames/archive with your name initials, before sending.
For instance: iep_task1.py or iep_tasks.rar
Send files to progressbg.python.course@gmail.com

These slides are based on

customised version of

Hakimel's reveal.js

framework