diff options
author | Raymond Hettinger <python@rcn.com> | 2003-07-11 18:58:11 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2003-07-11 18:58:11 (GMT) |
commit | fa6cce1fddd0a3f906082616b5d0f385dfac8ff4 (patch) | |
tree | 5a8a7b16bea3998fb2e22c8e5749ea851ae96aa2 | |
parent | 6d3e0186d64bc4f3520c2759b20752b6d224f45e (diff) | |
download | cpython-fa6cce1fddd0a3f906082616b5d0f385dfac8ff4.zip cpython-fa6cce1fddd0a3f906082616b5d0f385dfac8ff4.tar.gz cpython-fa6cce1fddd0a3f906082616b5d0f385dfac8ff4.tar.bz2 |
Minor fixups and added sections for iterators and generators.
-rw-r--r-- | Doc/tut/tut.tex | 120 |
1 files changed, 117 insertions, 3 deletions
diff --git a/Doc/tut/tut.tex b/Doc/tut/tut.tex index d38534b..05a8ea6 100644 --- a/Doc/tut/tut.tex +++ b/Doc/tut/tut.tex @@ -3731,7 +3731,7 @@ references, returning an integer and a method object, respectively. Class attributes can also be assigned to, so you can change the value of \code{MyClass.i} by assignment. \member{__doc__} is also a valid attribute, returning the docstring belonging to the class: \code{"A -simple example class"}). +simple example class"}. Class \emph{instantiation} uses function notation. Just pretend that the class object is a parameterless function that returns a new @@ -4128,7 +4128,8 @@ Instance method objects have attributes, too: \code{m.im_self} is the object of which the method is an instance, and \code{m.im_func} is the function object corresponding to the method. -\subsection{Exceptions Are Classes Too\label{exceptionClasses}} + +\section{Exceptions Are Classes Too\label{exceptionClasses}} User-defined exceptions are identified by classes as well. Using this mechanism it is possible to create extensible hierarchies of exceptions. @@ -4184,6 +4185,119 @@ finally the instance converted to a string using the built-in function \function{str()}. +\section{Iterators\label{iterators}} + +By now, you've probably noticed that most container objects can looped over +using a \code{for} statement: + +\begin{verbatim} +for element in [1, 2, 3]: + print element +for element in (1, 2, 3): + print element +for key in {'one':1, 'two':2}: + print key +for char in "123": + print char +for line in open("myfile.txt"): + print line +\end{verbatim} + +This style of access is clear, concise, and convenient. The use of iterators +pervades and unifies Python. Behind the scenes, the \code{for} statement calls +\function{iter()} on the container object. The function returns an iterator +object that defines the method \method{next()} which accesses elements in the +container one at a time. When there are no more elements, \method{next()} +raises a \exception{StopIteration} exception which tells the \code{for} loop +to terminate. This example shows how it all works: + +\begin{verbatim} +>>> s = 'abc' +>>> it = iter(s) +>>> it +<iterator object at 0x00A1DB50> +>>> it.next() +'a' +>>> it.next() +'b' +>>> it.next() +'c' +>>> it.next() + +Traceback (most recent call last): + File "<pyshell#6>", line 1, in -toplevel- + it.next() +StopIteration +\end{verbatim} + +Having seen the mechanics behind the iterator protocol, it is easy to add +iterator behavior to your classes. Define a \method{__iter__()} method +which returns an object with a \method{next()} method. If the class defines +\method{next()}, then \method{__iter__()} can just return \code{self}: + +\begin{verbatim} +>>> class Reverse: + "Iterator for looping over a sequence backwards" + def __init__(self, data): + self.data = data + self.index = len(data) + def __iter__(self): + return self + def next(self): + if self.index == 0: + raise StopIteration + self.index = self.index - 1 + return self.data[self.index] + +>>> for char in Reverse('spam'): + print char + +m +a +p +s +\end{verbatim} + + +\section{Generators\label{generators}} + +Generators are a simple and powerful tool for creating iterators. They are +written like regular functions but use the \keyword{yield} statement whenever +they want to return data. Each time the \method{next()} is called, the +generator resumes where it left-off (it remembers all the data values and +which statement was last executed). An example shows that generators can +be trivially easy to create: + +\begin{verbatim} +>>> def reverse(data): + for index in range(len(data)-1, -1, -1): + yield data[index] + +>>> for char in reverse('golf'): + print char + +f +l +o +g +\end{verbatim} + +Anything that can be done with generators can also be done with class based +iterators as described in the previous section. What makes generators so +compact is that the \method{__iter__()} and \method{next()} methods are +created automatically. + +Another other key feature is that the local variables and execution state +are automatically saved between calls. This made the function easier to write +and much more clear than an approach using class variables like +\code{self.index} and \code{self.data}. + +In addition to automatic method creation and saving program state, when +generators terminate, they automatically raise \exception{StopIteration}. +In combination, these features make it easy to create iterators with no +more effort than writing a regular function. + + \chapter{What Now? \label{whatNow}} Reading this tutorial has probably reinforced your interest in using @@ -4360,7 +4474,7 @@ out to be needed in most sessions with the interpreter. # bound to the Esc key by default (you can change it - see readline docs). # # Store the file in ~/.pystartup, and set an environment variable to point -# to it, e.g. "export PYTHONSTARTUP=/max/home/itamar/.pystartup" in bash. +# to it: "export PYTHONSTARTUP=/max/home/itamar/.pystartup" in bash. # # Note that PYTHONSTARTUP does *not* expand "~", so you have to put in the # full path to your home directory. |