@@ -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
@@ -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):
1013+ "Subsequences of the iterable from shortest to longest."
10181014 # 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,15 +1088,15 @@ 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
@@ -1109,7 +1105,7 @@ The following recipes have a more mathematical flavor:
11091105 # factor(99) → 3 3 11
11101106 # factor(1_000_000_000_000_007) → 47 59 360620266859
11111107 # factor(1_000_000_000_000_403) → 1000000000000403
1112- for prime in sieve(math. isqrt(n) + 1):
1108+ for prime in sieve(isqrt(n) + 1):
11131109 while not n % prime:
11141110 yield prime
11151111 n //= prime
@@ -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