Skip to content

Commit f2636d2

Browse files
authored
Misc itertool recipe improvements, mostly docstrings and comments (gh-109555)
1 parent 94c95d4 commit f2636d2

File tree

1 file changed

+42
-34
lines changed

1 file changed

+42
-34
lines changed

Doc/library/itertools.rst

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

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

@@ -1028,34 +1029,6 @@ The following recipes have a more mathematical flavor:
10281029
s = list(iterable)
10291030
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
10301031

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 not n % prime:
1052-
yield prime
1053-
n //= prime
1054-
if n == 1:
1055-
return
1056-
if n > 1:
1057-
yield n
1058-
10591032
def sum_of_squares(it):
10601033
"Add up the squares of the input values."
10611034
# sum_of_squares([10, 20, 30]) -> 1400
@@ -1073,14 +1046,21 @@ The following recipes have a more mathematical flavor:
10731046
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
10741047

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

10781058
Article: https://betterexplained.com/articles/intuitive-convolution/
10791059
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
10801060
"""
10811061
# convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
1082-
# convolve(data, [1, -1]) --> 1st finite difference (1st derivative)
1083-
# convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
1062+
# convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
1063+
# convolve(data, [1, -2, 1]) --> 2nd derivative estimate
10841064
kernel = tuple(kernel)[::-1]
10851065
n = len(kernel)
10861066
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
@@ -1104,8 +1084,8 @@ The following recipes have a more mathematical flavor:
11041084
# Evaluate x³ -4x² -17x + 60 at x = 2.5
11051085
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
11061086
n = len(coefficients)
1107-
if n == 0:
1108-
return x * 0 # coerce zero to the type of x
1087+
if not n:
1088+
return type(x)(0)
11091089
powers = map(pow, repeat(x), reversed(range(n)))
11101090
return math.sumprod(coefficients, powers)
11111091

@@ -1120,6 +1100,34 @@ The following recipes have a more mathematical flavor:
11201100
powers = reversed(range(1, n))
11211101
return list(map(operator.mul, coefficients, powers))
11221102

1103+
def sieve(n):
1104+
"Primes less than n."
1105+
# sieve(30) --> 2 3 5 7 11 13 17 19 23 29
1106+
if n > 2:
1107+
yield 2
1108+
start = 3
1109+
data = bytearray((0, 1)) * (n // 2)
1110+
limit = math.isqrt(n) + 1
1111+
for p in iter_index(data, 1, start, limit):
1112+
yield from iter_index(data, 1, start, p*p)
1113+
data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
1114+
start = p*p
1115+
yield from iter_index(data, 1, start)
1116+
1117+
def factor(n):
1118+
"Prime factors of n."
1119+
# factor(99) --> 3 3 11
1120+
# factor(1_000_000_000_000_007) --> 47 59 360620266859
1121+
# factor(1_000_000_000_000_403) --> 1000000000000403
1122+
for prime in sieve(math.isqrt(n) + 1):
1123+
while not n % prime:
1124+
yield prime
1125+
n //= prime
1126+
if n == 1:
1127+
return
1128+
if n > 1:
1129+
yield n
1130+
11231131
def nth_combination(iterable, r, index):
11241132
"Equivalent to list(combinations(iterable, r))[index]"
11251133
pool = tuple(iterable)
@@ -1295,7 +1303,7 @@ The following recipes have a more mathematical flavor:
12951303
>>> polynomial_eval([], Fraction(2, 3))
12961304
Fraction(0, 1)
12971305
>>> polynomial_eval([], Decimal('1.75'))
1298-
Decimal('0.00')
1306+
Decimal('0')
12991307
>>> polynomial_eval([11], 7) == 11
13001308
True
13011309
>>> polynomial_eval([11, 2], 7) == 11 * 7 + 2

0 commit comments

Comments
 (0)