[Python-checkins] r46250 - sandbox/trunk/Doc/functional.rst

andrew.kuchling python-checkins at python.org
Thu May 25 22:07:04 CEST 2006


Author: andrew.kuchling
Date: Thu May 25 22:07:04 2006
New Revision: 46250

Modified:
   sandbox/trunk/Doc/functional.rst
Log:
Add paragraph about sets; write half of itertools section; untabify

Modified: sandbox/trunk/Doc/functional.rst
==============================================================================
--- sandbox/trunk/Doc/functional.rst	(original)
+++ sandbox/trunk/Doc/functional.rst	Thu May 25 22:07:04 2006
@@ -215,10 +215,10 @@
 Y must be an iterator or some object for which ``iter()`` can create 
 an iterator.  These two statements are equivalent::
 
-	for i in iter(obj):
+        for i in iter(obj):
             print i
 
-	for i in obj:
+        for i in obj:
             print i
 
 Iterators can be materialized as lists or tuples by using the ``list()`` or ``tuple()``
@@ -302,10 +302,15 @@
 read each line of a file like this::
 
     for line in file:
-	# do something for each line
-	...
+        # do something for each line
+        ...
 
-XXX sets
+Sets can take their contents from an iterable and let you iterate over
+the set's elements::
+
+    S = set((2, 3, 5, 7, 11, 13))
+    for i in S:
+        print i
 
 
 
@@ -324,11 +329,11 @@
 a stream of strings with the following list comprehension::
 
         line_list = ['  line 1\n', 'line 2  \n', ...]
-	stripped_list = [line.strip() for line in line_list]
+        stripped_list = [line.strip() for line in line_list]
 
 You can select only certain elements by adding an ``"if"`` condition::
 
-	stripped_list = [line.strip() for line in line_list
+        stripped_list = [line.strip() for line in line_list
                          if line != ""]
 
 Note that in all case the resulting ``stripped_list`` is a Python list
@@ -339,10 +344,10 @@
 List comprehensions have the form::
 
     [ expression for expr in sequence1 
-		 for expr2 in sequence2
-		 for expr3 in sequence3 ...
-		 for exprN in sequenceN
-		 if condition ]
+                 for expr2 in sequence2
+                 for expr3 in sequence3 ...
+                 for exprN in sequenceN
+                 if condition ]
 
 The elements of the generated list will be the successive
 values of ``expression``.  The final ``if`` clause is
@@ -360,13 +365,13 @@
 Python code::
 
     for expr1 in sequence1:
-	for expr2 in sequence2:
-	...
-	    for exprN in sequenceN:
-		 if (condition):
-		      # Append the value of 
-		      # the expression to the 
-		      # resulting list.
+        for expr2 in sequence2:
+        ...
+            for exprN in sequenceN:
+                 if (condition):
+                      # Append the value of 
+                      # the expression to the 
+                      # resulting list.
 
 This means that when there are multiple ``for...in``
 clauses, the resulting list will be equal to the product of the
@@ -412,8 +417,8 @@
 Here's the simplest example of a generator function::
 
     def generate_ints(N):
-	for i in range(N):
-	    yield i
+        for i in range(N):
+            yield i
 
 Any function containing a ``yield`` keyword is a generator function;
 this is detected by Python's bytecode compiler which compiles the
@@ -475,12 +480,12 @@
 
     # A recursive generator that generates Tree leaves in in-order.
     def inorder(t):
-	if t:
-	    for x in inorder(t.left):
-		yield x
-	    yield t.label
-	    for x in inorder(t.right):
-		yield x
+        if t:
+            for x in inorder(t.left):
+                yield x
+            yield t.label
+            for x in inorder(t.right):
+                yield x
 
 Two other examples in ``test_generators.py`` produce
 solutions for the N-Queens problem (placing N queens on an NxN
@@ -531,14 +536,14 @@
 ::
 
     def counter (maximum):
-	i = 0
-	while i < maximum:
-	    val = (yield i)
-	    # If value provided, change counter
-	    if val is not None:
-		i = val
-	    else:
-		i += 1
+        i = 0
+        while i < maximum:
+            val = (yield i)
+            # If value provided, change counter
+            if val is not None:
+                i = val
+            else:
+                i += 1
 
 And here's an example of changing the counter:
 
@@ -554,7 +559,7 @@
     >>> print it.next()
     Traceback (most recent call last):
       File ``t.py'', line 15, in ?
-	print it.next()
+        print it.next()
     StopIteration
 
 Because ``yield`` will often be returning ``None``, you
@@ -595,37 +600,178 @@
 The itertools module
 -----------------------
 
-Small functions and the lambda statement
-----------------------------------------------
+The ``itertools`` module contains a number of commonly-used iterators
+as well as functions for combining iterators.  This section will
+introduce the module's contents using small examples.
+
+``itertools.count(n)`` returns an infinite stream of
+integers, increasing by 1 each time.  You can optionally supply the
+starting number, which defaults to 0::
+
+        itertools.count() =>
+          0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
+        itertools.count(10) =>
+          10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ...
+
+``itertools.cycle(iter)`` saves a copy of the contents of a provided
+iterable and returns a new iterator that returns its elements from
+first to last, and then repeats these elements infinitely.
+
+::
+
+        itertools.cycle([1,2,3,4,5]) =>
+          1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
+
+``itertools.repeat(elem, [n])`` returns the provided element ``n``
+times, or returns the element endlessly if ``n`` is not provided.
+
+::
+
+    itertools.repeat('abc') =>
+      abc, abc, abc, abc, abc, abc, abc, abc, abc, abc, ...
+    itertools.repeat('abc', 5) =>
+      abc, abc, abc, abc, abc
+
+``itertools.chain(iterA, iterB, ...)`` takes an arbitrary number of 
+iterables as input, and returns all the elements of the first iterator, 
+then all the elements of the second, until all of the iterables 
+have been exhausted.
+
+::
+
+    itertools.chain(['a', 'b', 'c'], (1, 2, 3)) =>
+      a, b, c, 1, 2, 3
+
+``itertools.izip(iterA, iterB, ...)`` takes one element from each iterable
+and returns them in a tuple::
+
+    itertools.izip(['a', 'b', 'c'], (1, 2, 3)) =>
+      ('a', 1), ('b', 2), ('c', 3)
+
+This iterator is intended to be used with iterables that are all of
+the same length.    If the iterables are of different lengths, 
+the resulting stream will be the same length as the shortest iterable.
+Unfortunately, if you passed in any iterators as arguments, 
+an element may have been taken from the longer iterators 
+and discarded, meaning that you can't keep using them; if you do, 
+you risk skipping a discarded element.
+
+::
+
+    itertools.izip(['a', 'b'], (1, 2, 3)) =>
+      ('a', 1), ('b', 2)
+
+
+``itertools.islice(iter, [start], stop, [step])`` returns a stream
+that's a slice of the iterator.  It can return the first ``stop``
+elements.  If you supply a starting index, you'll get ``stop-start``
+elements, and if you supply a value for ``step` elements will be
+skipped.  Unlike Python's string and list slicing, you can't use
+negative values for ``start``, ``stop``, or ``step``.
+
+::
+
+    itertools.islice(range(10), 8) =>
+      0, 1, 2, 3, 4, 5, 6, 7
+    itertools.islice(range(10), 2, 8) =>
+      2, 3, 4, 5, 6, 7
+    itertools.islice(range(10), 2, 8, 2) =>
+      2, 4, 6
+
+``itertools.tee(iter, [n])`` replicates an iterator; it returns ``n``
+independent iterators that will all return the contents of the source
+iterator.  If you don't supply a value for ``n``, the default is 2.
+Replicating iterators requires saving some of the contents of the source
+iterator, so this can consume significant memory if the iterator is large
+and one of the new iterators is consumed more than the others.
+
+::
+
+        itertools.tee( itertools.count() ) =>
+           iterA, iterB
+
+        where iterA ->
+           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
+
+        and   iterB ->
+           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
+
+
+Two functions are for calling other functions on the contents of an
+iterable.
+
+``itertools.imap(f, iterA, iterB, ...)`` returns 
+a stream containing ``f(iterA[0], iterB[0]), f(iterA[1], iterB[1]),
+f(iterA[2], iterB[2]), ...``::
+
+    itertools.imap(operator.add, [5, 6, 5], [1, 2, 3]) =>
+      6, 8, 8
+
+(The ``operator`` module contains a set of functions 
+corresponding to Python's operators.  Some examples are 
+``operator.add(a, b)`` (adds two values), 
+``operator.ne(a, b)`` (same as ``a!=b``),
+and 
+``operator.attrgetter('id')`` (returns a callable that
+fetches the ``"id"`` attribute), 
+
+``itertools.starmap(func, iter)`` assumes that the iterable will 
+return a stream of tuples, and calls ``f()`` using these tuples as the 
+arguments::
+
+    itertools.starmap(os.path.join, 
+                      [('/usr', 'bin', 'java'), ('/bin', 'python'),
+		       ('/usr', 'bin', 'perl'),('/usr', 'bin', 'ruby')])
+    =>
+      /usr/bin/java, /bin/python, /usr/bin/perl, /usr/bin/ruby
+
+
+
+.. comment
+
+    ifilter
+    ifilterfalse
+    takewhile
+    dropwhile
+    groupby
+
 
 Built-in functions
 ----------------------------------------------
 
 map(), filter(), reduce()
+os.walk()
+
+Small functions and the lambda statement
+----------------------------------------------
 
+XXX
+
+The functools modules
+----------------------------------------------
 
 .. comment
 
     Introduction
-	    Idea of FP
-		    Programs built out of functions
-		    Functions are strictly input-output, no internal state
-	    Opposed to OO programming, where objects have state
-
-	    Why FP?
-		    Formal provability
-			    Assignment is difficult to reason about
-			    Not very relevant to Python
-		    Modularity
-			    Small functions that do one thing
-		    Debuggability:
-			    Easy to test due to lack of state
-			    Easy to verify output from intermediate steps
-		    Composability
-			    You assemble a toolbox of functions that can be mixed
+            Idea of FP
+                    Programs built out of functions
+                    Functions are strictly input-output, no internal state
+            Opposed to OO programming, where objects have state
+
+            Why FP?
+                    Formal provability
+                            Assignment is difficult to reason about
+                            Not very relevant to Python
+                    Modularity
+                            Small functions that do one thing
+                    Debuggability:
+                            Easy to test due to lack of state
+                            Easy to verify output from intermediate steps
+                    Composability
+                            You assemble a toolbox of functions that can be mixed
 
     Tackling a problem
-	    Need a significant example
+            Need a significant example
 
     Iterators
     Generators
@@ -633,6 +779,16 @@
     List comprehensions
     Small functions and the lambda statement
     Built-in functions
-	    map
-	    filter
-	    reduce
+            map
+            filter
+            reduce
+
+.. comment
+
+    import itertools
+    def print_iter(it):
+         slice = itertools.islice(it, 10)
+         for elem in slice[:-1]:
+             sys.stdout.write(str(elem))
+             sys.stdout.write(', ')
+        print elem[-1]


More information about the Python-checkins mailing list