[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