mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
#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:
parent
44feda3cd0
commit
2a9c8e8cd3
1 changed files with 91 additions and 53 deletions
|
|
@ -3,7 +3,7 @@
|
||||||
********************************
|
********************************
|
||||||
|
|
||||||
:Author: A. M. Kuchling
|
:Author: A. M. Kuchling
|
||||||
:Release: 0.31
|
:Release: 0.32
|
||||||
|
|
||||||
In this document, we'll take a tour of Python's features suitable for
|
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
|
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
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
This section explains the basic concept of functional programming; if you're
|
This section explains the basic concept of functional programming; if
|
||||||
just interested in learning about Python language features, skip to the next
|
you're just interested in learning about Python language features,
|
||||||
section.
|
skip to the next section on :ref:`functional-howto-iterators`.
|
||||||
|
|
||||||
Programming languages support decomposing problems in several different ways:
|
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.
|
a few functions specialized for the current task.
|
||||||
|
|
||||||
|
|
||||||
|
.. _functional-howto-iterators:
|
||||||
|
|
||||||
Iterators
|
Iterators
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
@ -670,7 +672,7 @@ indexes at which certain conditions are met::
|
||||||
|
|
||||||
:func:`sorted(iterable, key=None, reverse=False) <sorted>` collects all the
|
: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
|
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. ::
|
constructed list's :meth:`~list.sort` method. ::
|
||||||
|
|
||||||
>>> import random
|
>>> import random
|
||||||
|
|
@ -836,7 +838,8 @@ Another group of functions chooses a subset of an iterator's elements based on a
|
||||||
predicate.
|
predicate.
|
||||||
|
|
||||||
:func:`itertools.filterfalse(predicate, iter) <itertools.filterfalse>` is the
|
: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()) =>
|
itertools.filterfalse(is_even, itertools.count()) =>
|
||||||
1, 3, 5, 7, 9, 11, 13, 15, ...
|
1, 3, 5, 7, 9, 11, 13, 15, ...
|
||||||
|
|
@ -864,6 +867,77 @@ iterable's results. ::
|
||||||
itertools.dropwhile(is_even, itertools.count()) =>
|
itertools.dropwhile(is_even, itertools.count()) =>
|
||||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
|
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
|
Grouping elements
|
||||||
-----------------
|
-----------------
|
||||||
|
|
@ -986,6 +1060,17 @@ write the obvious :keyword:`for` loop::
|
||||||
for i in [1,2,3]:
|
for i in [1,2,3]:
|
||||||
product *= i
|
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
|
The operator module
|
||||||
-------------------
|
-------------------
|
||||||
|
|
@ -1157,51 +1242,6 @@ Documentation for the :mod:`operator` module.
|
||||||
:pep:`342`: "Coroutines via Enhanced Generators" describes the new generator
|
:pep:`342`: "Coroutines via Enhanced Generators" describes the new generator
|
||||||
features in Python 2.5.
|
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
|
.. comment
|
||||||
|
|
||||||
Handy little function for printing part of an iterator -- used
|
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(str(elem))
|
||||||
sys.stdout.write(', ')
|
sys.stdout.write(', ')
|
||||||
print(elem[-1])
|
print(elem[-1])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue