Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2a9c8e8

Browse files
committed
#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.
1 parent 44feda3 commit 2a9c8e8

1 file changed

Lines changed: 91 additions & 53 deletions

File tree

Doc/howto/functional.rst

Lines changed: 91 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
********************************
44

55
:Author: A. M. Kuchling
6-
:Release: 0.31
6+
:Release: 0.32
77

88
In this document, we'll take a tour of Python's features suitable for
99
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
1515
Introduction
1616
============
1717

18-
This section explains the basic concept of functional programming; if you're
19-
just interested in learning about Python language features, skip to the next
20-
section.
18+
This section explains the basic concept of functional programming; if
19+
you're just interested in learning about Python language features,
20+
skip to the next section on :ref:`functional-howto-iterators`.
2121

2222
Programming languages support decomposing problems in several different ways:
2323

@@ -173,6 +173,8 @@ new programs by arranging existing functions in a new configuration and writing
173173
a few functions specialized for the current task.
174174

175175

176+
.. _functional-howto-iterators:
177+
176178
Iterators
177179
=========
178180

@@ -670,7 +672,7 @@ indexes at which certain conditions are met::
670672

671673
:func:`sorted(iterable, key=None, reverse=False) <sorted>` collects all the
672674
elements of the iterable into a list, sorts the list, and returns the sorted
673-
result. The *key*, and *reverse* arguments are passed through to the
675+
result. The *key* and *reverse* arguments are passed through to the
674676
constructed list's :meth:`~list.sort` method. ::
675677

676678
>>> import random
@@ -836,7 +838,8 @@ Another group of functions chooses a subset of an iterator's elements based on a
836838
predicate.
837839

838840
:func:`itertools.filterfalse(predicate, iter) <itertools.filterfalse>` is the
839-
opposite, returning all elements for which the predicate returns false::
841+
opposite of :func:`filter`, returning all elements for which the predicate
842+
returns false::
840843

841844
itertools.filterfalse(is_even, itertools.count()) =>
842845
1, 3, 5, 7, 9, 11, 13, 15, ...
@@ -864,6 +867,77 @@ iterable's results. ::
864867
itertools.dropwhile(is_even, itertools.count()) =>
865868
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...
866869

870+
:func:`itertools.compress(data, selectors) <itertools.compress>` takes two
871+
iterators and returns only those elements of *data* for which the corresponding
872+
element of *selectors* is true, stopping whenever either one is exhausted::
873+
874+
itertools.compress([1,2,3,4,5], [True, True, False, False, True]) =>
875+
1, 2, 5
876+
877+
878+
Combinatoric functions
879+
----------------------
880+
881+
The :func:`itertools.combinations(iterable, r) <itertools.combinations>`
882+
returns an iterator giving all possible *r*-tuple combinations of the
883+
elements contained in *iterable*. ::
884+
885+
itertools.combinations([1, 2, 3, 4, 5], 2) =>
886+
(1, 2), (1, 3), (1, 4), (1, 5),
887+
(2, 3), (2, 4), (2, 5),
888+
(3, 4), (3, 5),
889+
(4, 5)
890+
891+
itertools.combinations([1, 2, 3, 4, 5], 3) =>
892+
(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5),
893+
(2, 3, 4), (2, 3, 5), (2, 4, 5),
894+
(3, 4, 5)
895+
896+
The elements within each tuple remain in the same order as
897+
*iterable* returned them. For example, the number 1 is always before
898+
2, 3, 4, or 5 in the examples above. A similar function,
899+
:func:`itertools.permutations(iterable, r=None) <itertools.permutations>`,
900+
removes this constraint on the order, returning all possible
901+
arrangements of length *r*::
902+
903+
itertools.permutations([1, 2, 3, 4, 5], 2) =>
904+
(1, 2), (1, 3), (1, 4), (1, 5),
905+
(2, 1), (2, 3), (2, 4), (2, 5),
906+
(3, 1), (3, 2), (3, 4), (3, 5),
907+
(4, 1), (4, 2), (4, 3), (4, 5),
908+
(5, 1), (5, 2), (5, 3), (5, 4)
909+
910+
itertools.permutations([1, 2, 3, 4, 5]) =>
911+
(1, 2, 3, 4, 5), (1, 2, 3, 5, 4), (1, 2, 4, 3, 5),
912+
...
913+
(5, 4, 3, 2, 1)
914+
915+
If you don't supply a value for *r* the length of the iterable is used,
916+
meaning that all the elements are permuted.
917+
918+
Note that these functions produce all of the possible combinations by
919+
position and don't require that the contents of *iterable* are unique::
920+
921+
itertools.permutations('aba', 3) =>
922+
('a', 'b', 'a'), ('a', 'a', 'b'), ('b', 'a', 'a'),
923+
('b', 'a', 'a'), ('a', 'a', 'b'), ('a', 'b', 'a')
924+
925+
The identical tuple ``('a', 'a', 'b')`` occurs twice, but the two 'a'
926+
strings came from different positions.
927+
928+
The :func:`itertools.combinations_with_replacement(iterable, r) <itertools.combinations_with_replacement>`
929+
function relaxes a different constraint: elements can be repeated
930+
within a single tuple. Conceptually an element is selected for the
931+
first position of each tuple and then is replaced before the second
932+
element is selected. ::
933+
934+
itertools.combinations_with_replacement([1, 2, 3, 4, 5], 2) =>
935+
(1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
936+
(2, 2), (2, 3), (2, 4), (2, 5),
937+
(3, 3), (3, 4), (3, 5),
938+
(4, 4), (4, 5),
939+
(5, 5)
940+
867941

868942
Grouping elements
869943
-----------------
@@ -986,6 +1060,17 @@ write the obvious :keyword:`for` loop::
9861060
for i in [1,2,3]:
9871061
product *= i
9881062

1063+
A related function is `itertools.accumulate(iterable, func=operator.add) <itertools.accumulate`.
1064+
It performs the same calculation, but instead of returning only the
1065+
final result, :func:`accumulate` returns an iterator that also yields
1066+
each partial result::
1067+
1068+
itertools.accumulate([1,2,3,4,5]) =>
1069+
1, 3, 6, 10, 15
1070+
1071+
itertools.accumulate([1,2,3,4,5], operator.mul) =>
1072+
1, 2, 6, 24, 120
1073+
9891074

9901075
The operator module
9911076
-------------------
@@ -1157,51 +1242,6 @@ Documentation for the :mod:`operator` module.
11571242
:pep:`342`: "Coroutines via Enhanced Generators" describes the new generator
11581243
features in Python 2.5.
11591244

1160-
.. comment
1161-
1162-
Topics to place
1163-
-----------------------------
1164-
1165-
XXX os.walk()
1166-
1167-
XXX Need a large example.
1168-
1169-
But will an example add much? I'll post a first draft and see
1170-
what the comments say.
1171-
1172-
.. comment
1173-
1174-
Original outline:
1175-
Introduction
1176-
Idea of FP
1177-
Programs built out of functions
1178-
Functions are strictly input-output, no internal state
1179-
Opposed to OO programming, where objects have state
1180-
1181-
Why FP?
1182-
Formal provability
1183-
Assignment is difficult to reason about
1184-
Not very relevant to Python
1185-
Modularity
1186-
Small functions that do one thing
1187-
Debuggability:
1188-
Easy to test due to lack of state
1189-
Easy to verify output from intermediate steps
1190-
Composability
1191-
You assemble a toolbox of functions that can be mixed
1192-
1193-
Tackling a problem
1194-
Need a significant example
1195-
1196-
Iterators
1197-
Generators
1198-
The itertools module
1199-
List comprehensions
1200-
Small functions and the lambda statement
1201-
Built-in functions
1202-
map
1203-
filter
1204-
12051245
.. comment
12061246
12071247
Handy little function for printing part of an iterator -- used
@@ -1214,5 +1254,3 @@ features in Python 2.5.
12141254
sys.stdout.write(str(elem))
12151255
sys.stdout.write(', ')
12161256
print(elem[-1])
1217-
1218-

0 commit comments

Comments
 (0)