Skip to content

Commit 0015a9a

Browse files
[3.12] Misc itertool recipe improvements, mostly docstrings and comments (gh-109555) (#109572)
(cherry picked from commit f2636d2) Co-authored-by: Raymond Hettinger <[email protected]>
1 parent 9e4ac21 commit 0015a9a

File tree

1 file changed

+44
-37
lines changed

1 file changed

+44
-37
lines changed

Doc/library/itertools.rst

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ which incur interpreter overhead.
844844
return next(islice(iterable, n, None), default)
845845

846846
def quantify(iterable, pred=bool):
847-
"Count how many times the predicate is True"
847+
"Given a predicate that returns True or False, count the True results."
848848
return sum(map(pred, iterable))
849849

850850
def all_equal(iterable):
@@ -1028,36 +1028,6 @@ The following recipes have a more mathematical flavor:
10281028
s = list(iterable)
10291029
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
10301030

1031-
def sieve(n):
1032-
"Primes less than n."
1033-
# sieve(30) --> 2 3 5 7 11 13 17 19 23 29
1034-
if n > 2:
1035-
yield 2
1036-
start = 3
1037-
data = bytearray((0, 1)) * (n // 2)
1038-
limit = math.isqrt(n) + 1
1039-
for p in iter_index(data, 1, start, limit):
1040-
yield from iter_index(data, 1, start, p*p)
1041-
data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
1042-
start = p*p
1043-
yield from iter_index(data, 1, start)
1044-
1045-
def factor(n):
1046-
"Prime factors of n."
1047-
# factor(99) --> 3 3 11
1048-
# factor(1_000_000_000_000_007) --> 47 59 360620266859
1049-
# factor(1_000_000_000_000_403) --> 1000000000000403
1050-
for prime in sieve(math.isqrt(n) + 1):
1051-
while True:
1052-
if n % prime:
1053-
break
1054-
yield prime
1055-
n //= prime
1056-
if n == 1:
1057-
return
1058-
if n > 1:
1059-
yield n
1060-
10611031
def sum_of_squares(it):
10621032
"Add up the squares of the input values."
10631033
# sum_of_squares([10, 20, 30]) -> 1400
@@ -1075,14 +1045,21 @@ The following recipes have a more mathematical flavor:
10751045
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
10761046

10771047
def convolve(signal, kernel):
1078-
"""Linear convolution of two iterables.
1048+
"""Discrete linear convolution of two iterables.
1049+
1050+
The kernel is fully consumed before the calculations begin.
1051+
The signal is consumed lazily and can be infinite.
1052+
1053+
Convolutions are mathematically commutative.
1054+
If the signal and kernel are swapped,
1055+
the output will be the same.
10791056

10801057
Article: https://betterexplained.com/articles/intuitive-convolution/
10811058
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
10821059
"""
10831060
# convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
1084-
# convolve(data, [1, -1]) --> 1st finite difference (1st derivative)
1085-
# convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
1061+
# convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
1062+
# convolve(data, [1, -2, 1]) --> 2nd derivative estimate
10861063
kernel = tuple(kernel)[::-1]
10871064
n = len(kernel)
10881065
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
@@ -1106,8 +1083,8 @@ The following recipes have a more mathematical flavor:
11061083
# Evaluate x³ -4x² -17x + 60 at x = 2.5
11071084
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
11081085
n = len(coefficients)
1109-
if n == 0:
1110-
return x * 0 # coerce zero to the type of x
1086+
if not n:
1087+
return type(x)(0)
11111088
powers = map(pow, repeat(x), reversed(range(n)))
11121089
return math.sumprod(coefficients, powers)
11131090

@@ -1122,6 +1099,36 @@ The following recipes have a more mathematical flavor:
11221099
powers = reversed(range(1, n))
11231100
return list(map(operator.mul, coefficients, powers))
11241101

1102+
def sieve(n):
1103+
"Primes less than n."
1104+
# sieve(30) --> 2 3 5 7 11 13 17 19 23 29
1105+
if n > 2:
1106+
yield 2
1107+
start = 3
1108+
data = bytearray((0, 1)) * (n // 2)
1109+
limit = math.isqrt(n) + 1
1110+
for p in iter_index(data, 1, start, limit):
1111+
yield from iter_index(data, 1, start, p*p)
1112+
data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
1113+
start = p*p
1114+
yield from iter_index(data, 1, start)
1115+
1116+
def factor(n):
1117+
"Prime factors of n."
1118+
# factor(99) --> 3 3 11
1119+
# factor(1_000_000_000_000_007) --> 47 59 360620266859
1120+
# factor(1_000_000_000_000_403) --> 1000000000000403
1121+
for prime in sieve(math.isqrt(n) + 1):
1122+
while True:
1123+
if n % prime:
1124+
break
1125+
yield prime
1126+
n //= prime
1127+
if n == 1:
1128+
return
1129+
if n > 1:
1130+
yield n
1131+
11251132
def nth_combination(iterable, r, index):
11261133
"Equivalent to list(combinations(iterable, r))[index]"
11271134
pool = tuple(iterable)
@@ -1297,7 +1304,7 @@ The following recipes have a more mathematical flavor:
12971304
>>> polynomial_eval([], Fraction(2, 3))
12981305
Fraction(0, 1)
12991306
>>> polynomial_eval([], Decimal('1.75'))
1300-
Decimal('0.00')
1307+
Decimal('0')
13011308
>>> polynomial_eval([11], 7) == 11
13021309
True
13031310
>>> polynomial_eval([11, 2], 7) == 11 * 7 + 2

0 commit comments

Comments
 (0)