summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2024-03-15 00:41:38 (GMT)
committerGitHub <noreply@github.com>2024-03-15 00:41:38 (GMT)
commite4ec4459265f9d4b947abd82c82466b569db21a4 (patch)
tree1260b9662e76da525c16af4ff7ec7494bf6382d5
parent988246a17b69e7c3077c7456bc50d04d6f153c5d (diff)
downloadcpython-e4ec4459265f9d4b947abd82c82466b569db21a4.zip
cpython-e4ec4459265f9d4b947abd82c82466b569db21a4.tar.gz
cpython-e4ec4459265f9d4b947abd82c82466b569db21a4.tar.bz2
[3.12] Minor improvements to the itertools documentation (gh-116833) (gh-116838)
-rw-r--r--Doc/library/itertools.rst178
1 files changed, 94 insertions, 84 deletions
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index e57fd6e..e36ba8e 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -41,9 +41,9 @@ operator can be mapped across two vectors to form an efficient dot-product:
================== ================= ================================================= =========================================
Iterator Arguments Results Example
================== ================= ================================================= =========================================
-:func:`count` [start[, step]] start, start+step, start+2*step, ... ``count(10) --> 10 11 12 13 14 ...``
-:func:`cycle` p p0, p1, ... plast, p0, p1, ... ``cycle('ABCD') --> A B C D A B C D ...``
-:func:`repeat` elem [,n] elem, elem, elem, ... endlessly or up to n times ``repeat(10, 3) --> 10 10 10``
+:func:`count` [start[, step]] start, start+step, start+2*step, ... ``count(10) → 10 11 12 13 14 ...``
+:func:`cycle` p p0, p1, ... plast, p0, p1, ... ``cycle('ABCD') → A B C D A B C D ...``
+:func:`repeat` elem [,n] elem, elem, elem, ... endlessly or up to n times ``repeat(10, 3) → 10 10 10``
================== ================= ================================================= =========================================
**Iterators terminating on the shortest input sequence:**
@@ -51,20 +51,20 @@ Iterator Arguments Results
============================ ============================ ================================================= =============================================================
Iterator Arguments Results Example
============================ ============================ ================================================= =============================================================
-:func:`accumulate` p [,func] p0, p0+p1, p0+p1+p2, ... ``accumulate([1,2,3,4,5]) --> 1 3 6 10 15``
-:func:`batched` p, n (p0, p1, ..., p_n-1), ... ``batched('ABCDEFG', n=3) --> ABC DEF G``
-:func:`chain` p, q, ... p0, p1, ... plast, q0, q1, ... ``chain('ABC', 'DEF') --> A B C D E F``
-:func:`chain.from_iterable` iterable p0, p1, ... plast, q0, q1, ... ``chain.from_iterable(['ABC', 'DEF']) --> A B C D E F``
-:func:`compress` data, selectors (d[0] if s[0]), (d[1] if s[1]), ... ``compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F``
-:func:`dropwhile` predicate, seq seq[n], seq[n+1], starting when predicate fails ``dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1``
-:func:`filterfalse` predicate, seq elements of seq where predicate(elem) fails ``filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8``
+:func:`accumulate` p [,func] p0, p0+p1, p0+p1+p2, ... ``accumulate([1,2,3,4,5]) → 1 3 6 10 15``
+:func:`batched` p, n (p0, p1, ..., p_n-1), ... ``batched('ABCDEFG', n=3) → ABC DEF G``
+:func:`chain` p, q, ... p0, p1, ... plast, q0, q1, ... ``chain('ABC', 'DEF') → A B C D E F``
+:func:`chain.from_iterable` iterable p0, p1, ... plast, q0, q1, ... ``chain.from_iterable(['ABC', 'DEF']) → A B C D E F``
+:func:`compress` data, selectors (d[0] if s[0]), (d[1] if s[1]), ... ``compress('ABCDEF', [1,0,1,0,1,1]) → A C E F``
+:func:`dropwhile` predicate, seq seq[n], seq[n+1], starting when predicate fails ``dropwhile(lambda x: x<5, [1,4,6,4,1]) → 6 4 1``
+:func:`filterfalse` predicate, seq elements of seq where predicate(elem) fails ``filterfalse(lambda x: x%2, range(10)) → 0 2 4 6 8``
:func:`groupby` iterable[, key] sub-iterators grouped by value of key(v)
-:func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) --> C D E F G``
-:func:`pairwise` iterable (p[0], p[1]), (p[1], p[2]) ``pairwise('ABCDEFG') --> AB BC CD DE EF FG``
-:func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000``
-:func:`takewhile` predicate, seq seq[0], seq[1], until predicate fails ``takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4``
+:func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) → C D E F G``
+:func:`pairwise` iterable (p[0], p[1]), (p[1], p[2]) ``pairwise('ABCDEFG') → AB BC CD DE EF FG``
+:func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) → 32 9 1000``
+:func:`takewhile` predicate, seq seq[0], seq[1], until predicate fails ``takewhile(lambda x: x<5, [1,4,6,4,1]) → 1 4``
:func:`tee` it, n it1, it2, ... itn splits one iterator into n
-:func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-``
+:func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') → Ax By C- D-``
============================ ============================ ================================================= =============================================================
**Combinatoric iterators:**
@@ -84,7 +84,7 @@ Examples Results
``product('ABCD', repeat=2)`` ``AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD``
``permutations('ABCD', 2)`` ``AB AC AD BA BC BD CA CB CD DA DB DC``
``combinations('ABCD', 2)`` ``AB AC AD BC BD CD``
-``combinations_with_replacement('ABCD', 2)`` ``AA AB AC AD BB BC BD CC CD DD``
+``combinations_with_replacement('ABCD', 2)`` ``AA AB AC AD BB BC BD CC CD DD``
============================================== =============================================================
@@ -119,9 +119,9 @@ loops that truncate the stream.
def accumulate(iterable, func=operator.add, *, initial=None):
'Return running totals'
- # accumulate([1,2,3,4,5]) --> 1 3 6 10 15
- # accumulate([1,2,3,4,5], initial=100) --> 100 101 103 106 110 115
- # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
+ # accumulate([1,2,3,4,5]) → 1 3 6 10 15
+ # accumulate([1,2,3,4,5], initial=100) → 100 101 103 106 110 115
+ # accumulate([1,2,3,4,5], operator.mul) → 1 2 6 24 120
it = iter(iterable)
total = initial
if initial is None:
@@ -191,7 +191,7 @@ loops that truncate the stream.
Roughly equivalent to::
def batched(iterable, n):
- # batched('ABCDEFG', 3) --> ABC DEF G
+ # batched('ABCDEFG', 3) → ABC DEF G
if n < 1:
raise ValueError('n must be at least one')
it = iter(iterable)
@@ -209,7 +209,7 @@ loops that truncate the stream.
Roughly equivalent to::
def chain(*iterables):
- # chain('ABC', 'DEF') --> A B C D E F
+ # chain('ABC', 'DEF') → A B C D E F
for it in iterables:
for element in it:
yield element
@@ -221,7 +221,7 @@ loops that truncate the stream.
single iterable argument that is evaluated lazily. Roughly equivalent to::
def from_iterable(iterables):
- # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
+ # chain.from_iterable(['ABC', 'DEF']) → A B C D E F
for it in iterables:
for element in it:
yield element
@@ -242,8 +242,8 @@ loops that truncate the stream.
Roughly equivalent to::
def combinations(iterable, r):
- # combinations('ABCD', 2) --> AB AC AD BC BD CD
- # combinations(range(4), 3) --> 012 013 023 123
+ # combinations('ABCD', 2) → AB AC AD BC BD CD
+ # combinations(range(4), 3) → 012 013 023 123
pool = tuple(iterable)
n = len(pool)
if r > n:
@@ -291,7 +291,7 @@ loops that truncate the stream.
Roughly equivalent to::
def combinations_with_replacement(iterable, r):
- # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
+ # combinations_with_replacement('ABC', 2) → AA AB AC BB BC CC
pool = tuple(iterable)
n = len(pool)
if not n and r:
@@ -331,7 +331,7 @@ loops that truncate the stream.
Roughly equivalent to::
def compress(data, selectors):
- # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
+ # compress('ABCDEF', [1,0,1,0,1,1]) → A C E F
return (d for d, s in zip(data, selectors) if s)
.. versionadded:: 3.1
@@ -344,8 +344,8 @@ loops that truncate the stream.
Also, used with :func:`zip` to add sequence numbers. Roughly equivalent to::
def count(start=0, step=1):
- # count(10) --> 10 11 12 13 14 ...
- # count(2.5, 0.5) --> 2.5 3.0 3.5 ...
+ # count(10) → 10 11 12 13 14 ...
+ # count(2.5, 0.5) → 2.5 3.0 3.5 ...
n = start
while True:
yield n
@@ -365,7 +365,7 @@ loops that truncate the stream.
indefinitely. Roughly equivalent to::
def cycle(iterable):
- # cycle('ABCD') --> A B C D A B C D A B C D ...
+ # cycle('ABCD') → A B C D A B C D A B C D ...
saved = []
for element in iterable:
yield element
@@ -386,7 +386,7 @@ loops that truncate the stream.
start-up time. Roughly equivalent to::
def dropwhile(predicate, iterable):
- # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
+ # dropwhile(lambda x: x<5, [1,4,6,4,1]) → 6 4 1
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
@@ -402,7 +402,7 @@ loops that truncate the stream.
that are false. Roughly equivalent to::
def filterfalse(predicate, iterable):
- # filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
+ # filterfalse(lambda x: x%2, range(10)) → 0 2 4 6 8
if predicate is None:
predicate = bool
for x in iterable:
@@ -439,8 +439,8 @@ loops that truncate the stream.
:func:`groupby` is roughly equivalent to::
class groupby:
- # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
- # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
+ # [k for k, g in groupby('AAAABBBCCDAABBB')] → A B C D A B
+ # [list(g) for k, g in groupby('AAAABBBCCD')] → AAAA BBB CC D
def __init__(self, iterable, key=None):
if key is None:
@@ -491,10 +491,10 @@ loops that truncate the stream.
Roughly equivalent to::
def islice(iterable, *args):
- # islice('ABCDEFG', 2) --> A B
- # islice('ABCDEFG', 2, 4) --> C D
- # islice('ABCDEFG', 2, None) --> C D E F G
- # islice('ABCDEFG', 0, None, 2) --> A C E G
+ # islice('ABCDEFG', 2) → A B
+ # islice('ABCDEFG', 2, 4) → C D
+ # islice('ABCDEFG', 2, None) → C D E F G
+ # islice('ABCDEFG', 0, None, 2) → A C E G
s = slice(*args)
start, stop, step = s.start or 0, s.stop or sys.maxsize, s.step or 1
it = iter(range(start, stop, step))
@@ -527,10 +527,12 @@ loops that truncate the stream.
Roughly equivalent to::
def pairwise(iterable):
- # pairwise('ABCDEFG') --> AB BC CD DE EF FG
- a, b = tee(iterable)
- next(b, None)
- return zip(a, b)
+ # pairwise('ABCDEFG') → AB BC CD DE EF FG
+ iterator = iter(iterable)
+ a = next(iterator, None)
+ for b in iterator:
+ yield a, b
+ a = b
.. versionadded:: 3.10
@@ -554,8 +556,8 @@ loops that truncate the stream.
Roughly equivalent to::
def permutations(iterable, r=None):
- # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
- # permutations(range(3)) --> 012 021 102 120 201 210
+ # permutations('ABCD', 2) → AB AC AD BA BC BD CA CB CD DA DB DC
+ # permutations(range(3)) → 012 021 102 120 201 210
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
@@ -613,8 +615,8 @@ loops that truncate the stream.
actual implementation does not build up intermediate results in memory::
def product(*args, repeat=1):
- # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
- # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
+ # product('ABCD', 'xy') → Ax Ay Bx By Cx Cy Dx Dy
+ # product(range(2), repeat=3) → 000 001 010 011 100 101 110 111
pools = [tuple(pool) for pool in args] * repeat
result = [[]]
for pool in pools:
@@ -634,7 +636,7 @@ loops that truncate the stream.
Roughly equivalent to::
def repeat(object, times=None):
- # repeat(10, 3) --> 10 10 10
+ # repeat(10, 3) → 10 10 10
if times is None:
while True:
yield object
@@ -662,7 +664,7 @@ loops that truncate the stream.
equivalent to::
def starmap(function, iterable):
- # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
+ # starmap(pow, [(2,5), (3,2), (10,3)]) → 32 9 1000
for args in iterable:
yield function(*args)
@@ -673,7 +675,7 @@ loops that truncate the stream.
predicate is true. Roughly equivalent to::
def takewhile(predicate, iterable):
- # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
+ # takewhile(lambda x: x<5, [1,4,6,4,1]) → 1 4
for x in iterable:
if predicate(x):
yield x
@@ -733,7 +735,7 @@ loops that truncate the stream.
Iteration continues until the longest iterable is exhausted. Roughly equivalent to::
def zip_longest(*args, fillvalue=None):
- # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D-
+ # zip_longest('ABCD', 'xy', fillvalue='-') → Ax By C- D-
iterators = [iter(it) for it in args]
num_active = len(iterators)
if not num_active:
@@ -808,7 +810,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
def prepend(value, iterable):
"Prepend a single value in front of an iterable."
- # prepend(1, [2, 3, 4]) --> 1 2 3 4
+ # prepend(1, [2, 3, 4]) → 1 2 3 4
return chain([value], iterable)
def tabulate(function, start=0):
@@ -834,7 +836,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
def tail(n, iterable):
"Return an iterator over the last n items."
- # tail(3, 'ABCDEFG') --> E F G
+ # tail(3, 'ABCDEFG') → E F G
return iter(collections.deque(iterable, maxlen=n))
def consume(iterator, n=None):
@@ -857,26 +859,27 @@ and :term:`generators <generator>` which incur interpreter overhead.
def first_true(iterable, default=False, predicate=None):
"Returns the first true value or the *default* if there is no true value."
- # first_true([a,b,c], x) --> a or b or c or x
- # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
+ # first_true([a,b,c], x) → a or b or c or x
+ # first_true([a,b], x, f) → a if f(a) else b if f(b) else x
return next(filter(predicate, iterable), default)
def all_equal(iterable, key=None):
"Returns True if all the elements are equal to each other."
+ # all_equal('4٤໔4৪', key=int) → True
return len(take(2, groupby(iterable, key))) <= 1
def unique_justseen(iterable, key=None):
"List unique elements, preserving order. Remember only the element just seen."
- # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
- # unique_justseen('ABBcCAD', str.casefold) --> A B c A D
+ # unique_justseen('AAAABBBCCDAABBB') → A B C D A B
+ # unique_justseen('ABBcCAD', str.casefold) → A B c A D
if key is None:
return map(operator.itemgetter(0), groupby(iterable))
return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
- # unique_everseen('AAAABBBCCDAABBB') --> A B C D
- # unique_everseen('ABBcCAD', str.casefold) --> A B c D
+ # unique_everseen('AAAABBBCCDAABBB') → A B C D
+ # unique_everseen('ABBcCAD', str.casefold) → A B c D
seen = set()
if key is None:
for element in filterfalse(seen.__contains__, iterable):
@@ -891,7 +894,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
def sliding_window(iterable, n):
"Collect data into overlapping fixed-length chunks or blocks."
- # sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG
+ # sliding_window('ABCDEFG', 4) → ABCD BCDE CDEF DEFG
it = iter(iterable)
window = collections.deque(islice(it, n-1), maxlen=n)
for x in it:
@@ -900,9 +903,9 @@ and :term:`generators <generator>` which incur interpreter overhead.
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
"Collect data into non-overlapping fixed-length chunks or blocks."
- # grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
- # grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
- # grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
+ # grouper('ABCDEFG', 3, fillvalue='x') → ABC DEF Gxx
+ # grouper('ABCDEFG', 3, incomplete='strict') → ABC DEF ValueError
+ # grouper('ABCDEFG', 3, incomplete='ignore') → ABC DEF
iterators = [iter(iterable)] * n
match incomplete:
case 'fill':
@@ -916,7 +919,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
def roundrobin(*iterables):
"Visit input iterables in a cycle until each is exhausted."
- # roundrobin('ABC', 'D', 'EF') --> A D E B F C
+ # roundrobin('ABC', 'D', 'EF') → A D E B F C
# Algorithm credited to George Sakkis
iterators = map(iter, iterables)
for num_active in range(len(iterables), 0, -1):
@@ -928,19 +931,19 @@ and :term:`generators <generator>` which incur interpreter overhead.
If *predicate* is slow, consider wrapping it with functools.lru_cache().
"""
- # partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9
+ # partition(is_odd, range(10)) → 0 2 4 6 8 and 1 3 5 7 9
t1, t2 = tee(iterable)
return filterfalse(predicate, t1), filter(predicate, t2)
def subslices(seq):
"Return all contiguous non-empty subslices of a sequence."
- # subslices('ABCD') --> A AB ABC ABCD B BC BCD C CD D
+ # subslices('ABCD') → A AB ABC ABCD B BC BCD C CD D
slices = starmap(slice, combinations(range(len(seq) + 1), 2))
return map(operator.getitem, repeat(seq), slices)
def iter_index(iterable, value, start=0, stop=None):
"Return indices where a value occurs in a sequence or iterable."
- # iter_index('AABCADEAF', 'A') --> 0 1 4 7
+ # iter_index('AABCADEAF', 'A') → 0 1 4 7
seq_index = getattr(iterable, 'index', None)
if seq_index is None:
# Path for general iterables
@@ -964,7 +967,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
Converts a call-until-exception interface to an iterator interface.
"""
- # iter_except(d.popitem, KeyError) --> non-blocking dictionary iterator
+ # iter_except(d.popitem, KeyError) → non-blocking dictionary iterator
try:
if first is not None:
yield first()
@@ -979,28 +982,28 @@ The following recipes have a more mathematical flavor:
.. testcode::
def powerset(iterable):
- "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
+ "powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
def sum_of_squares(iterable):
"Add up the squares of the input values."
- # sum_of_squares([10, 20, 30]) --> 1400
+ # sum_of_squares([10, 20, 30]) → 1400
return math.sumprod(*tee(iterable))
def reshape(matrix, cols):
"Reshape a 2-D matrix to have a given number of columns."
- # reshape([(0, 1), (2, 3), (4, 5)], 3) --> (0, 1, 2), (3, 4, 5)
+ # reshape([(0, 1), (2, 3), (4, 5)], 3) → (0, 1, 2), (3, 4, 5)
return batched(chain.from_iterable(matrix), cols)
def transpose(matrix):
"Swap the rows and columns of a 2-D matrix."
- # transpose([(1, 2, 3), (11, 22, 33)]) --> (1, 11) (2, 22) (3, 33)
+ # transpose([(1, 2, 3), (11, 22, 33)]) → (1, 11) (2, 22) (3, 33)
return zip(*matrix, strict=True)
def matmul(m1, m2):
"Multiply two matrices."
- # matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) --> (49, 80), (41, 60)
+ # matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) → (49, 80), (41, 60)
n = len(m2[0])
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
@@ -1015,10 +1018,10 @@ The following recipes have a more mathematical flavor:
Article: https://betterexplained.com/articles/intuitive-convolution/
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
"""
- # convolve([1, -1, -20], [1, -3]) --> 1 -4 -17 60
- # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
- # convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
- # convolve(data, [1, -2, 1]) --> 2nd derivative estimate
+ # convolve([1, -1, -20], [1, -3]) → 1 -4 -17 60
+ # convolve(data, [0.25, 0.25, 0.25, 0.25]) → Moving average (blur)
+ # convolve(data, [1/2, 0, -1/2]) → 1st derivative estimate
+ # convolve(data, [1, -2, 1]) → 2nd derivative estimate
kernel = tuple(kernel)[::-1]
n = len(kernel)
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
@@ -1030,7 +1033,7 @@ The following recipes have a more mathematical flavor:
(x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60
"""
- # polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60]
+ # polynomial_from_roots([5, -4, 3]) → [1, -4, -17, 60]
factors = zip(repeat(1), map(operator.neg, roots))
return list(functools.reduce(convolve, factors, [1]))
@@ -1040,7 +1043,7 @@ The following recipes have a more mathematical flavor:
Computes with better numeric stability than Horner's method.
"""
# Evaluate x³ -4x² -17x + 60 at x = 5
- # polynomial_eval([1, -4, -17, 60], x=5) --> 0
+ # polynomial_eval([1, -4, -17, 60], x=5) → 0
n = len(coefficients)
if not n:
return type(x)(0)
@@ -1053,14 +1056,14 @@ The following recipes have a more mathematical flavor:
f(x) = x³ -4x² -17x + 60
f'(x) = 3x² -8x -17
"""
- # polynomial_derivative([1, -4, -17, 60]) --> [3, -8, -17]
+ # polynomial_derivative([1, -4, -17, 60]) → [3, -8, -17]
n = len(coefficients)
powers = reversed(range(1, n))
return list(map(operator.mul, coefficients, powers))
def sieve(n):
"Primes less than n."
- # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
+ # sieve(30) → 2 3 5 7 11 13 17 19 23 29
if n > 2:
yield 2
start = 3
@@ -1074,9 +1077,9 @@ The following recipes have a more mathematical flavor:
def factor(n):
"Prime factors of n."
- # factor(99) --> 3 3 11
- # factor(1_000_000_000_000_007) --> 47 59 360620266859
- # factor(1_000_000_000_000_403) --> 1000000000000403
+ # factor(99) → 3 3 11
+ # factor(1_000_000_000_000_007) → 47 59 360620266859
+ # factor(1_000_000_000_000_403) → 1000000000000403
for prime in sieve(math.isqrt(n) + 1):
while not n % prime:
yield prime
@@ -1089,7 +1092,7 @@ The following recipes have a more mathematical flavor:
def totient(n):
"Count of natural numbers up to n that are coprime to n."
# https://mathworld.wolfram.com/TotientFunction.html
- # totient(12) --> 4 because len([1, 5, 7, 11]) == 4
+ # totient(12) → 4 because len([1, 5, 7, 11]) == 4
for p in unique_justseen(factor(n)):
n -= n // p
return n
@@ -1555,6 +1558,13 @@ The following recipes have a more mathematical flavor:
>>> ranges = [range(5, 1000), range(4, 3000), range(0), range(3, 2000), range(2, 5000), range(1, 3500)]
>>> collections.Counter(roundrobin(ranges)) == collections.Counter(ranges)
True
+ >>> # Verify that the inputs are consumed lazily
+ >>> input_iterators = list(map(iter, ['abcd', 'ef', '', 'ghijk', 'l', 'mnopqr']))
+ >>> output_iterator = roundrobin(*input_iterators)
+ >>> ''.join(islice(output_iterator, 10))
+ 'aeglmbfhnc'
+ >>> ''.join(chain(*input_iterators))
+ 'dijkopqr'
>>> def is_odd(x):
... return x % 2 == 1
@@ -1664,7 +1674,7 @@ The following recipes have a more mathematical flavor:
def triplewise(iterable):
"Return overlapping triplets from an iterable"
- # triplewise('ABCDEFG') --> ABC BCD CDE DEF EFG
+ # triplewise('ABCDEFG') → ABC BCD CDE DEF EFG
for (a, _), (b, c) in pairwise(pairwise(iterable)):
yield a, b, c