@@ -30,11 +30,6 @@ For instance, SML provides a tabulation tool: ``tabulate(f)`` which produces a
3030sequence ``f(0), f(1), ... ``. The same effect can be achieved in Python
3131by combining :func: `map ` and :func: `count ` to form ``map(f, count()) ``.
3232
33- These tools and their built-in counterparts also work well with the high-speed
34- functions in the :mod: `operator ` module. For example, the multiplication
35- operator can be mapped across two vectors to form an efficient dot-product:
36- ``sum(starmap(operator.mul, zip(vec1, vec2, strict=True))) ``.
37-
3833
3934**Infinite iterators: **
4035
@@ -686,7 +681,7 @@ loops that truncate the stream.
686681 consumed from the input iterator and there is no way to access it.
687682 This could be an issue if an application wants to further consume the
688683 input iterator after *takewhile * has been run to exhaustion. To work
689- around this problem, consider using `more-iterools before_and_after()
684+ around this problem, consider using `more-itertools before_and_after()
690685 <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.before_and_after> `_
691686 instead.
692687
@@ -843,12 +838,11 @@ and :term:`generators <generator>` which incur interpreter overhead.
843838
844839.. testcode ::
845840
846- import collections
847- import contextlib
848- import functools
849- import math
850- import operator
851- import random
841+ from collections import deque
842+ from contextlib import suppress
843+ from functools import reduce
844+ from math import sumprod, isqrt
845+ from operator import itemgetter, getitem, mul, neg
852846
853847 def take(n, iterable):
854848 "Return first n items of the iterable as a list."
@@ -863,11 +857,11 @@ and :term:`generators <generator>` which incur interpreter overhead.
863857 "Return function(0), function(1), ..."
864858 return map(function, count(start))
865859
866- def repeatfunc(func , times=None, *args):
867- "Repeat calls to func with specified arguments."
860+ def repeatfunc(function , times=None, *args):
861+ "Repeat calls to a function with specified arguments."
868862 if times is None:
869- return starmap(func , repeat(args))
870- return starmap(func , repeat(args, times))
863+ return starmap(function , repeat(args))
864+ return starmap(function , repeat(args, times))
871865
872866 def flatten(list_of_lists):
873867 "Flatten one level of nesting."
@@ -885,13 +879,13 @@ and :term:`generators <generator>` which incur interpreter overhead.
885879 def tail(n, iterable):
886880 "Return an iterator over the last n items."
887881 # tail(3, 'ABCDEFG') → E F G
888- return iter(collections. deque(iterable, maxlen=n))
882+ return iter(deque(iterable, maxlen=n))
889883
890884 def consume(iterator, n=None):
891885 "Advance the iterator n-steps ahead. If n is None, consume entirely."
892886 # Use functions that consume iterators at C speed.
893887 if n is None:
894- collections. deque(iterator, maxlen=0)
888+ deque(iterator, maxlen=0)
895889 else:
896890 next(islice(iterator, n, n), None)
897891
@@ -919,8 +913,8 @@ and :term:`generators <generator>` which incur interpreter overhead.
919913 # unique_justseen('AAAABBBCCDAABBB') → A B C D A B
920914 # unique_justseen('ABBcCAD', str.casefold) → A B c A D
921915 if key is None:
922- return map(operator. itemgetter(0), groupby(iterable))
923- return map(next, map(operator. itemgetter(1), groupby(iterable, key)))
916+ return map(itemgetter(0), groupby(iterable))
917+ return map(next, map(itemgetter(1), groupby(iterable, key)))
924918
925919 def unique_everseen(iterable, key=None):
926920 "Yield unique elements, preserving order. Remember all elements ever seen."
@@ -941,13 +935,14 @@ and :term:`generators <generator>` which incur interpreter overhead.
941935 def unique(iterable, key=None, reverse=False):
942936 "Yield unique elements in sorted order. Supports unhashable inputs."
943937 # unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4]
944- return unique_justseen(sorted(iterable, key=key, reverse=reverse), key=key)
938+ sequenced = sorted(iterable, key=key, reverse=reverse)
939+ return unique_justseen(sequenced, key=key)
945940
946941 def sliding_window(iterable, n):
947942 "Collect data into overlapping fixed-length chunks or blocks."
948943 # sliding_window('ABCDEFG', 4) → ABCD BCDE CDEF DEFG
949944 iterator = iter(iterable)
950- window = collections. deque(islice(iterator, n - 1), maxlen=n)
945+ window = deque(islice(iterator, n - 1), maxlen=n)
951946 for x in iterator:
952947 window.append(x)
953948 yield tuple(window)
@@ -981,7 +976,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
981976 "Return all contiguous non-empty subslices of a sequence."
982977 # subslices('ABCD') → A AB ABC ABCD B BC BCD C CD D
983978 slices = starmap(slice, combinations(range(len(seq) + 1), 2))
984- return map(operator. getitem, repeat(seq), slices)
979+ return map(getitem, repeat(seq), slices)
985980
986981 def iter_index(iterable, value, start=0, stop=None):
987982 "Return indices where a value occurs in a sequence or iterable."
@@ -995,39 +990,40 @@ and :term:`generators <generator>` which incur interpreter overhead.
995990 else:
996991 stop = len(iterable) if stop is None else stop
997992 i = start
998- with contextlib. suppress(ValueError):
993+ with suppress(ValueError):
999994 while True:
1000995 yield (i := seq_index(value, i, stop))
1001996 i += 1
1002997
1003- def iter_except(func , exception, first=None):
998+ def iter_except(function , exception, first=None):
1004999 "Convert a call-until-exception interface to an iterator interface."
10051000 # iter_except(d.popitem, KeyError) → non-blocking dictionary iterator
1006- with contextlib. suppress(exception):
1001+ with suppress(exception):
10071002 if first is not None:
10081003 yield first()
10091004 while True:
1010- yield func ()
1005+ yield function ()
10111006
10121007
10131008The following recipes have a more mathematical flavor:
10141009
10151010.. testcode ::
10161011
10171012 def powerset(iterable):
1018- "powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
1013+ "Subsequences of the iterable from shortest to longest."
1014+ # powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)
10191015 s = list(iterable)
10201016 return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
10211017
10221018 def sum_of_squares(iterable):
10231019 "Add up the squares of the input values."
10241020 # sum_of_squares([10, 20, 30]) → 1400
1025- return math. sumprod(*tee(iterable))
1021+ return sumprod(*tee(iterable))
10261022
1027- def reshape(matrix, cols ):
1023+ def reshape(matrix, columns ):
10281024 "Reshape a 2-D matrix to have a given number of columns."
10291025 # reshape([(0, 1), (2, 3), (4, 5)], 3) → (0, 1, 2), (3, 4, 5)
1030- return batched(chain.from_iterable(matrix), cols , strict=True)
1026+ return batched(chain.from_iterable(matrix), columns , strict=True)
10311027
10321028 def transpose(matrix):
10331029 "Swap the rows and columns of a 2-D matrix."
@@ -1038,7 +1034,7 @@ The following recipes have a more mathematical flavor:
10381034 "Multiply two matrices."
10391035 # matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) → (49, 80), (41, 60)
10401036 n = len(m2[0])
1041- return batched(starmap(math. sumprod, product(m1, transpose(m2))), n)
1037+ return batched(starmap(sumprod, product(m1, transpose(m2))), n)
10421038
10431039 def convolve(signal, kernel):
10441040 """Discrete linear convolution of two iterables.
@@ -1059,16 +1055,16 @@ The following recipes have a more mathematical flavor:
10591055 n = len(kernel)
10601056 padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
10611057 windowed_signal = sliding_window(padded_signal, n)
1062- return map(math. sumprod, repeat(kernel), windowed_signal)
1058+ return map(sumprod, repeat(kernel), windowed_signal)
10631059
10641060 def polynomial_from_roots(roots):
10651061 """Compute a polynomial's coefficients from its roots.
10661062
10671063 (x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60
10681064 """
10691065 # polynomial_from_roots([5, -4, 3]) → [1, -4, -17, 60]
1070- factors = zip(repeat(1), map(operator. neg, roots))
1071- return list(functools. reduce(convolve, factors, [1]))
1066+ factors = zip(repeat(1), map(neg, roots))
1067+ return list(reduce(convolve, factors, [1]))
10721068
10731069 def polynomial_eval(coefficients, x):
10741070 """Evaluate a polynomial at a specific value.
@@ -1081,7 +1077,7 @@ The following recipes have a more mathematical flavor:
10811077 if not n:
10821078 return type(x)(0)
10831079 powers = map(pow, repeat(x), reversed(range(n)))
1084- return math. sumprod(coefficients, powers)
1080+ return sumprod(coefficients, powers)
10851081
10861082 def polynomial_derivative(coefficients):
10871083 """Compute the first derivative of a polynomial.
@@ -1092,29 +1088,24 @@ The following recipes have a more mathematical flavor:
10921088 # polynomial_derivative([1, -4, -17, 60]) → [3, -8, -17]
10931089 n = len(coefficients)
10941090 powers = reversed(range(1, n))
1095- return list(map(operator. mul, coefficients, powers))
1091+ return list(map(mul, coefficients, powers))
10961092
10971093 def sieve(n):
10981094 "Primes less than n."
10991095 # sieve(30) → 2 3 5 7 11 13 17 19 23 29
11001096 if n > 2:
11011097 yield 2
11021098 data = bytearray((0, 1)) * (n // 2)
1103- for p in iter_index(data, 1, start=3, stop=math. isqrt(n) + 1):
1099+ for p in iter_index(data, 1, start=3, stop=isqrt(n) + 1):
11041100 data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
11051101 yield from iter_index(data, 1, start=3)
11061102
1107- def is_prime(n):
1108- "Return True if n is prime."
1109- # is_prime(1_000_000_000_000_403) → True
1110- return n > 1 and all(n % p for p in sieve(math.isqrt(n) + 1))
1111-
11121103 def factor(n):
11131104 "Prime factors of n."
11141105 # factor(99) → 3 3 11
11151106 # factor(1_000_000_000_000_007) → 47 59 360620266859
11161107 # factor(1_000_000_000_000_403) → 1000000000000403
1117- for prime in sieve(math. isqrt(n) + 1):
1108+ for prime in sieve(isqrt(n) + 1):
11181109 while not n % prime:
11191110 yield prime
11201111 n //= prime
@@ -1123,6 +1114,11 @@ The following recipes have a more mathematical flavor:
11231114 if n > 1:
11241115 yield n
11251116
1117+ def is_prime(n):
1118+ "Return True if n is prime."
1119+ # is_prime(1_000_000_000_000_403) → True
1120+ return n > 1 and next(factor(n)) == n
1121+
11261122 def totient(n):
11271123 "Count of natural numbers up to n that are coprime to n."
11281124 # https://mathworld.wolfram.com/TotientFunction.html
@@ -1740,7 +1736,7 @@ The following recipes have a more mathematical flavor:
17401736
17411737 # Old recipes and their tests which are guaranteed to continue to work.
17421738
1743- def sumprod (vec1, vec2):
1739+ def old_sumprod_recipe (vec1, vec2):
17441740 "Compute a sum of products."
17451741 return sum(starmap(operator.mul, zip(vec1, vec2, strict=True)))
17461742
@@ -1823,7 +1819,7 @@ The following recipes have a more mathematical flavor:
18231819 32
18241820
18251821
1826- >>> sumprod ([1 ,2 ,3 ], [4 ,5 ,6 ])
1822+ >>> old_sumprod_recipe ([1 ,2 ,3 ], [4 ,5 ,6 ])
18271823 32
18281824
18291825
0 commit comments