This document provides an overview of iterators, generators, and the Python Imaging Library (PIL) basics in Python. It discusses how iterators allow iteration over objects using the iterator protocol with __iter__ and next() methods. Generators are lazy functions that yield values and can be created via generator factories or comprehensions. The PIL allows loading, saving, and modifying image files in Python through functions like Image.new(), getpixel(), putpixel(), and ImageDraw for drawing primitives.
4. Iterator Protocol
●
●
Iterators are objects that allow us to iterate over other
objects one item at a time (e.g., iterate over values in a
range, over lines in a file, over nodes in a tree, over
records in a database)
In principle, any Python object can be turned into an
iterator so long as it implements the Iterator Protocol
5. Iterator Protocol
●
●
●
●
In Python 2.7, the Iterator Protocol consists of two
methods __iter__ and next()
__iter__ returns the iterator object (typically self) that
implements the next() method
The next() method on first call returns the first element,
on the second call – the second element, etc
When there are no more elements a call to next() should
raise a StopIteration exception
7. Built-in iter() Function
●
If you know that a Python object is iterable, you can use the builtin function iter() to obtain an iterator for that object
>>> lstit = iter([1, 2, 3, 4])
>>> lstit.next()
1
>>> lstit.next()
2
>>> strit = iter('abcd efg')
>>> strit.next()
'a'
9. Design Patterns
●
●
In OOP, design patterns are referred to
standardized ways of capturing specify types of
behavior
Design patterns typically evolve bottom-up: after
repeating the same task for a few times, a
software engineer or a team of software engineers
may notice a sequence of actions that may be
worth reusing – and a design pattern is born
10. Factory Design Pattern
●
●
●
Factory is an OOP design pattern
generalizes the constructor concept
that
In some circumstances, it is conceptually easier or
more efficient to create a class whose objects
produce other types of objects
A factory class has a method for constructing each
type of object it is designed to construct
12. Generators
●
●
●
A generator is a lazy function that remembers its state
from call to call
A lazy function returns (or, in Python terminology, yields)
its values one at a time without giving up control
Generators are typically used for handling really large
ranges or solving combinatorial optimization problems
13. Definition
●
●
Let us use this definition: a generator is an object that
iterates over some data in a lazy fashion
This definition has several implications:
Generators are iterators
Generators are associated with specific data
Generators are lazy: they yield data items one at a
time and without necessarily storing all data items
in memory
14. Generator Construction
●
●
●
In Python, there are two ways to construct
generators:
generator
factories
and
generator
comprehensions (generator
expressions)
Generator factories are used when more complex
generators are required
Generator comprehensions are used for simpler
generators
16. Generator Factories
●
●
Every Python function that has the keyword yield
in its body defines a generator factory
For example:
def gen_factory_1234():
yield 1
yield 2
yield 3
yield 4
17. Generator Factories
●
Why is gen_factory_1234 a generator factory?
●
Because on each invocation it creates a new object
>>> g1 = gen_factory_123()
>>> g1.next()
1
>>> g1.next()
2
>>> g1.next()
3
>>> g1.next()
4
>>> g1.next()
StopIteration Exception
18. Generator Objects
●
●
●
Unlike functions that return values, generators
yield values and remember the point at which the
last value is yielded
On the next invocation, a generator pick up from
the point at which the previous value was yielded
When there are no more values to yield,
StopIteration is raised
19. Generator Factories
●
Here is a more generic way of defining a generator
factory that yields each number in a range
def gen_factory_range(lower, upper):
for i in xrange(lower, upper+1):
yield i
20. Generator Objects
●
●
●
Generator objects are one-time only: once a
generator object goes over its data (if the number
of data items is finite), it cannot be restarted
You can create as many generator objects
coupled to the same data as you want
Generator objects can be consumed by standard
Python sequence constructors or sequence
processors
21. Examples
## two generators defined over the same data
>>> gfr1 = gen_factory_range(10, 15)
>>> gfr2 = gen_factory_range(10, 15)
## two generator objects consumed by zip constructor
>>> zip(gfr1, gfr2)
[(10, 10), (11, 11), (12, 12), (13, 13), (14, 14), (15, 15)]
>>> gfr3 = gen_factory_range(10, 15)
## generator object consumed by list constructor
>>> list(gfr3)
[10, 11, 12, 13, 14, 15]
## generator object consumed by sum
>>> sum(gen_factory_range(1, 5))
15
22. Examples
## generator object consumed by max
>>> max(gen_factory_range(1, 5))
5
## generator object consumed by set constructor
>>> set(gen_factory_range(1, 5))
set([1, 2, 3, 4, 5])
## generator object used by the boolean in operator
>>> 5 in gen_factory_range(1, 5)
True
24. Generator Comprehension
●
●
The most straightforward method of obtaining a generator is through
generator comprehensions (aka generator expressions)
Generator comprehension is similar to list comprehension except it
uses parentheses around generator expressions and it does not
enumerate all elements in the range
>>> g1 = (x**3 for x in xrange(1, 100001))
>>> g1.next()
1
>>> g1.next()
8
>>> g2 = (i**2+10 for i in xrange(1, 100001))
>>> g2.next()
11
26. Creating New Images
●
Image.new(mode, size [, color])
●
The mode of an image describes the way it represents colors
'1' : Black and white (monochrome), one bit per pixel.
'L' : Gray scale, one 8-bit byte per pixel.
'RGB' : True red-green-blue color, three bytes per pixel.
●
size is a tuple (width, height)
●
color is optional
If missing, the new image is filled with black
If present, the new image is filled with that color
29. Getting Pixel Values
●
im.getpixel((x,y))
## im is an Image object
## x,y is a tuple (x, y)
●
(0, 0) is the top left corner
●
Example:
>>> im = Image.new("RGB", (100, 50), (0, 0, 255))
>>> im.getpixel((0, 0))
31. Reading Images from Files
## 1. Create an image
>>> im1 = Image.new('RGB', (100, 100), (0, 255, 0))
## 2. Save an image
>>> im1.save('/home/user/Pictures/im1.bmp')
## 3. Open an image from an existing file
>>> im2 = Image.open('/home/user/Pictures/im1.bmp')
>>> print im2.format, im2.size, im2.mode
BMP (100, 100) RGB
32. Colors in PIL
●
●
●
●
Colors depend on the mode of the image
In RGB mode, colors are returned as 3-tuples (red,
green, blue)
Values range from 0 upto 255
Common colors can set with string values, e.g., 'white',
'black', 'red'
34. Drawing
●
●
It is possible to use putpixel() to draw various figures
but this can get tedious and error-prone
ImageDraw is used to draw simple 2D graphics:
Lines
Ellipses
Text
35. Using ImageDraw
●
First, create an Image object:
●
Image.new() or Image.open()
Second, create an ImageDraw object from the Image object:
import Image
import ImageDraw
im = Image.new('RGB', (100, 100))
Draw = ImageDraw.Draw(im)
●
Third, use the ImageDraw object to draw various figures in the Image
●
Fourth, save the Image in a file if necessary
36. Draw.line()
>>> draw.line(xy, options)
●
●
●
Draws a line between the coordinates in the xy list.
The coordinate list can be any sequence object
containing either 2-tuples [ (x, y), … ] or numeric values [
x, y, … ]. It should contain at least two coordinates.
The fill option gives the color to use for the line.