Session 10 - Generators
Today you will learn how to make your classes iterable. You will learn how to create a generator function and how to write this in an easier to read manner using a generator expression. You will also gain inside into why a function in python is an object and how to make your own object callable.
We will look at Iterator classes
1class Compute:
2 def __iter__(self):
3 self.last = 0
4 return self
5
6 def __next__(self):
7 rv = self.last
8 self.last += 1
9 if self.last > 10:
10 raise StopIteration()
11 sleep(.5)
12 return rv
13
14 for i in Compute():
15 print(i)
And see how it can be done in an easier to read and use manner with a generator function
1def compute():
2 for i in range(10):
3 yield i
And write a generator expression.
1(i for i in range(10))
Learning goals
Understand how functions are abstractions of a class.
- Create memory and time efficient code using:
Iterator Classes
generator functions and
generator expressoions.
Materials
Introduction to Python Generators (excl. Using Advanced Generator Methods & Creating Data Pipelines With Generators)
Exercises
ex1: Python Students
Based on the Student class below, create a PythonStudents class that acts as a collection of students. The class should implement the iterations protocol (iter(), next() and StopIteration). When iterated the Pythod_students object should return the name of each student in the list.
1 class PythonStudents:
2 pass
3
4
5
6
7 class Student:
8
9 def __init__(self, name, cpr):
10 self.name = name
11 self.cpr = cpr
12
13 @property
14 def name(self):
15 return self.__name
16
17 @name.setter
18 def name(self, name):
19 self.__name = name.capitalize()
20
21 def __add__(self, student):
22 return Student('Anna the daugther', 1234)
23
24 def __str__(self):
25 return f'{self.name}, {self.cpr}'
26
27 def __repr__(self):
28 return f'{self.__dict__}'
ex2: School of students
In this exercise you start out by having a list of names, and a list of majors.
Your job is to create:
A list of dictionaries of students (ie: students = [{‘id’: 1,’name’: ‘Claus’, ‘major’: ‘Math’}]), cretated in a normal function that returns the result.
A Generator that “returns” a generator object. So the student is yield instead of returned.
Both functions should do the same, but one returns a list and one a generator object.
1names = ['John', 'Corey', 'Adam', 'Steve', 'Rick', 'Thomas']
2majors = ['Math', 'Engineering', 'CompSci', 'Arts', 'Business']
3
4def students_list(num_students):
5 pass
6
7def students_generator(num_students):
8 pass
9
10people = students_list(1000000)
11people = students_generator(1000000)
ex3: Range Mimic
Create a “clone” of the build in range() function, by doing an iterator class.
In the documentation you can read the following about the range function.
class range(start, stop, step=1)
Rather than being a function, range is actually an immutable sequence type, as documented in Ranges and Sequence Types — list, tuple, range.
So the range function is actually not a function, it is a class that implements the iterator protocol.
>>> r = range(1, 10, 2)
>>> i = iter(r)
>>> next(i)
1
Now do the same, but use a generator function instead.