]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] Misc itertool recipe improvements, mostly docstrings and comments (gh-109555...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 22 Sep 2023 12:43:40 +0000 (05:43 -0700)
committerGitHub <noreply@github.com>
Fri, 22 Sep 2023 12:43:40 +0000 (14:43 +0200)
(cherry picked from commit f2636d2c45aae0a04960dcfbc7d9a2a8a36ba3bc)

Co-authored-by: Raymond Hettinger <rhettinger@users.noreply.github.com>
Doc/library/itertools.rst

index 7fc1ae913cdba53a8c5ea0220d035c6971e68b98..8a1c83aa3a2804c8f3e115404ebd945e496b96bb 100644 (file)
@@ -844,7 +844,7 @@ which incur interpreter overhead.
        return next(islice(iterable, n, None), default)
 
    def quantify(iterable, pred=bool):
-       "Count how many times the predicate is True"
+       "Given a predicate that returns True or False, count the True results."
        return sum(map(pred, iterable))
 
    def all_equal(iterable):
@@ -1028,36 +1028,6 @@ The following recipes have a more mathematical flavor:
        s = list(iterable)
        return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
 
-   def sieve(n):
-       "Primes less than n."
-       # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
-       if n > 2:
-           yield 2
-       start = 3
-       data = bytearray((0, 1)) * (n // 2)
-       limit = math.isqrt(n) + 1
-       for p in iter_index(data, 1, start, limit):
-           yield from iter_index(data, 1, start, p*p)
-           data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
-           start = p*p
-       yield from iter_index(data, 1, start)
-
-   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
-       for prime in sieve(math.isqrt(n) + 1):
-           while True:
-               if n % prime:
-                   break
-               yield prime
-               n //= prime
-               if n == 1:
-                   return
-       if n > 1:
-           yield n
-
    def sum_of_squares(it):
        "Add up the squares of the input values."
        # sum_of_squares([10, 20, 30]) -> 1400
@@ -1075,14 +1045,21 @@ The following recipes have a more mathematical flavor:
        return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
 
    def convolve(signal, kernel):
-       """Linear convolution of two iterables.
+       """Discrete linear convolution of two iterables.
+
+       The kernel is fully consumed before the calculations begin.
+       The signal is consumed lazily and can be infinite.
+
+       Convolutions are mathematically commutative.
+       If the signal and kernel are swapped,
+       the output will be the same.
 
        Article:  https://betterexplained.com/articles/intuitive-convolution/
        Video:    https://www.youtube.com/watch?v=KuXjwB4LzSA
        """
        # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
-       # convolve(data, [1, -1]) --> 1st finite difference (1st derivative)
-       # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
+       # 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))
@@ -1106,8 +1083,8 @@ The following recipes have a more mathematical flavor:
        # Evaluate x³ -4x² -17x + 60 at x = 2.5
        # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
        n = len(coefficients)
-       if n == 0:
-           return x * 0  # coerce zero to the type of x
+       if not n:
+           return type(x)(0)
        powers = map(pow, repeat(x), reversed(range(n)))
        return math.sumprod(coefficients, powers)
 
@@ -1122,6 +1099,36 @@ The following recipes have a more mathematical flavor:
        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
+       if n > 2:
+           yield 2
+       start = 3
+       data = bytearray((0, 1)) * (n // 2)
+       limit = math.isqrt(n) + 1
+       for p in iter_index(data, 1, start, limit):
+           yield from iter_index(data, 1, start, p*p)
+           data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
+           start = p*p
+       yield from iter_index(data, 1, start)
+
+   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
+       for prime in sieve(math.isqrt(n) + 1):
+           while True:
+               if n % prime:
+                   break
+               yield prime
+               n //= prime
+               if n == 1:
+                   return
+       if n > 1:
+           yield n
+
    def nth_combination(iterable, r, index):
        "Equivalent to list(combinations(iterable, r))[index]"
        pool = tuple(iterable)
@@ -1297,7 +1304,7 @@ The following recipes have a more mathematical flavor:
     >>> polynomial_eval([], Fraction(2, 3))
     Fraction(0, 1)
     >>> polynomial_eval([], Decimal('1.75'))
-    Decimal('0.00')
+    Decimal('0')
     >>> polynomial_eval([11], 7) == 11
     True
     >>> polynomial_eval([11, 2], 7) == 11 * 7 + 2