#17955: minor updates to Functional howto

* Describe compress() and accumulate()
* Add a subsection on combinatoric functions.
* Add a forward link to skip the theoretical discussion in the first section.
* Clarify what filterfalse() is the opposite of.
* Remove the old outline and some notes at the end.
* Various small edits.
This commit is contained in:
Andrew Kuchling 2013-05-20 10:14:53 -04:00
parent 44feda3cd0
commit 2a9c8e8cd3
1 changed files with 91 additions and 53 deletions

View File

@ -3,7 +3,7 @@
********************************
:Author: A. M. Kuchling
:Release: 0.31
:Release: 0.32
In this document, we'll take a tour of Python's features suitable for
implementing programs in a functional style. After an introduction to the
@ -15,9 +15,9 @@ concepts of functional programming, we'll look at language features such as
Introduction
============
This section explains the basic concept of functional programming; if you're
just interested in learning about Python language features, skip to the next
section.
This section explains the basic concept of functional programming; if
you're just interested in learning about Python language features,
skip to the next section on :ref:`functional-howto-iterators`.
Programming languages support decomposing problems in several different ways:
@ -173,6 +173,8 @@ new programs by arranging existing functions in a new configuration and writing
a few functions specialized for the current task.
.. _functional-howto-iterators:
Iterators
=========
@ -670,7 +672,7 @@ indexes at which certain conditions are met::
:func:`sorted(iterable, key=None, reverse=False) <sorted>` collects all the
elements of the iterable into a list, sorts the list, and returns the sorted
result. The *key*, and *reverse* arguments are passed through to the
result. The *key* and *reverse* arguments are passed through to the
constructed list's :meth:`~list.sort` method. ::
>>> import random
@ -836,7 +838,8 @@ Another group of functions chooses a subset of an iterator's elements based on a
predicate.
:func:`itertools.filterfalse(predicate, iter) <itertools.filterfalse>` is the
opposite, returning all elements for which the predicate returns false::
opposite of :func:`filter`, returning all elements for which the predicate
returns false::
itertools.filterfalse(is_even, itertools.count()) =>
1, 3, 5, 7, 9, 11, 13, 15, ...
@ -864,6 +867,77 @@ iterable's results. ::
itertools.dropwhile(is_even, itertools.count()) =>
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
:func:`itertools.compress(data, selectors) <itertools.compress>` takes two
iterators and returns only those elements of *data* for which the corresponding
element of *selectors* is true, stopping whenever either one is exhausted::
itertools.compress([1,2,3,4,5], [True, True, False, False, True]) =>
1, 2, 5
Combinatoric functions
----------------------
The :func:`itertools.combinations(iterable, r) <itertools.combinations>`
returns an iterator giving all possible *r*-tuple combinations of the
elements contained in *iterable*. ::
itertools.combinations([1, 2, 3, 4, 5], 2) =>
(1, 2), (1, 3), (1, 4), (1, 5),
(2, 3), (2, 4), (2, 5),
(3, 4), (3, 5),
(4, 5)
itertools.combinations([1, 2, 3, 4, 5], 3) =>
(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5),
(2, 3, 4), (2, 3, 5), (2, 4, 5),
(3, 4, 5)
The elements within each tuple remain in the same order as
*iterable* returned them. For example, the number 1 is always before
2, 3, 4, or 5 in the examples above. A similar function,
:func:`itertools.permutations(iterable, r=None) <itertools.permutations>`,
removes this constraint on the order, returning all possible
arrangements of length *r*::
itertools.permutations([1, 2, 3, 4, 5], 2) =>
(1, 2), (1, 3), (1, 4), (1, 5),
(2, 1), (2, 3), (2, 4), (2, 5),
(3, 1), (3, 2), (3, 4), (3, 5),
(4, 1), (4, 2), (4, 3), (4, 5),
(5, 1), (5, 2), (5, 3), (5, 4)
itertools.permutations([1, 2, 3, 4, 5]) =>
(1, 2, 3, 4, 5), (1, 2, 3, 5, 4), (1, 2, 4, 3, 5),
...
(5, 4, 3, 2, 1)
If you don't supply a value for *r* the length of the iterable is used,
meaning that all the elements are permuted.
Note that these functions produce all of the possible combinations by
position and don't require that the contents of *iterable* are unique::
itertools.permutations('aba', 3) =>
('a', 'b', 'a'), ('a', 'a', 'b'), ('b', 'a', 'a'),
('b', 'a', 'a'), ('a', 'a', 'b'), ('a', 'b', 'a')
The identical tuple ``('a', 'a', 'b')`` occurs twice, but the two 'a'
strings came from different positions.
The :func:`itertools.combinations_with_replacement(iterable, r) <itertools.combinations_with_replacement>`
function relaxes a different constraint: elements can be repeated
within a single tuple. Conceptually an element is selected for the
first position of each tuple and then is replaced before the second
element is selected. ::
itertools.combinations_with_replacement([1, 2, 3, 4, 5], 2) =>
(1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
(2, 2), (2, 3), (2, 4), (2, 5),
(3, 3), (3, 4), (3, 5),
(4, 4), (4, 5),
(5, 5)
Grouping elements
-----------------
@ -986,6 +1060,17 @@ write the obvious :keyword:`for` loop::
for i in [1,2,3]:
product *= i
A related function is `itertools.accumulate(iterable, func=operator.add) <itertools.accumulate`.
It performs the same calculation, but instead of returning only the
final result, :func:`accumulate` returns an iterator that also yields
each partial result::
itertools.accumulate([1,2,3,4,5]) =>
1, 3, 6, 10, 15
itertools.accumulate([1,2,3,4,5], operator.mul) =>
1, 2, 6, 24, 120
The operator module
-------------------
@ -1157,51 +1242,6 @@ Documentation for the :mod:`operator` module.
:pep:`342`: "Coroutines via Enhanced Generators" describes the new generator
features in Python 2.5.
.. comment
Topics to place
-----------------------------
XXX os.walk()
XXX Need a large example.
But will an example add much? I'll post a first draft and see
what the comments say.
.. comment
Original outline:
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
Tackling a problem
Need a significant example
Iterators
Generators
The itertools module
List comprehensions
Small functions and the lambda statement
Built-in functions
map
filter
.. comment
Handy little function for printing part of an iterator -- used
@ -1214,5 +1254,3 @@ features in Python 2.5.
sys.stdout.write(str(elem))
sys.stdout.write(', ')
print(elem[-1])