From 2bd199b1abc4401501cde2b04f4060fe0bbf991c Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 30 Nov 2024 11:36:19 -0600 Subject: [PATCH 1/5] Add is_prime() for a short, motivated example of using sieve(). --- Doc/library/itertools.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index c138e903fa5a0f..706c2617363f11 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -1099,6 +1099,11 @@ The following recipes have a more mathematical flavor: data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p))) yield from iter_index(data, 1, start=3) + def is_prime(n): + "Return True if n is prime." + # is_prime(1_000_000_000_000_403) → True + return n > 1 and all(n % p for p in sieve(math.isqrt(n) + 1)) + def factor(n): "Prime factors of n." # factor(99) → 3 3 11 @@ -1475,6 +1480,22 @@ The following recipes have a more mathematical flavor: True + >>> small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] + >>> list(filter(is_prime, range(-100, 100))) == small_primes + True + >>> carmichael = {561, 1105, 1729, 2465, 2821, 6601, 8911} # https://oeis.org/A002997 + >>> any(map(is_prime, carmichael)) + False + >>> is_prime(128_884_753_939) # large prime + True + >>> is_prime(999953 * 999983) # large semiprime + False + >>> is_prime(1_000_000_000_000_007) # factor() example + False + >>> is_prime(1_000_000_000_000_403) # factor() example + True + + >>> list(factor(99)) # Code example 1 [3, 3, 11] >>> list(factor(1_000_000_000_000_007)) # Code example 2 From e920ce381ebf9ec5c3afed8125eea3a413967b88 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 30 Nov 2024 12:10:56 -0600 Subject: [PATCH 2/5] Add loops() recipe to demonstrate a common use of repeat() --- Doc/library/itertools.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 706c2617363f11..87179ecfb38c73 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -882,6 +882,11 @@ and :term:`generators ` which incur interpreter overhead. # tail(3, 'ABCDEFG') → E F G return iter(collections.deque(iterable, maxlen=n)) + def loops(n): + "Loop n times. Like range(n) but faster because no integers are produced." + # for _ in loops(100): ... + return repeat(None, n) + def consume(iterator, n=None): "Advance the iterator n-steps ahead. If n is None, consume entirely." # Use functions that consume iterators at C speed. @@ -1216,6 +1221,16 @@ The following recipes have a more mathematical flavor: [] + >>> for _ in loops(5): + ... print('hi') + ... + hi + hi + hi + hi + hi + + >>> it = iter(range(10)) >>> consume(it, 3) >>> # Verify the input is consumed lazily From c6abe7036a9298fcf431369560f9a5047c99d529 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 30 Nov 2024 12:18:28 -0600 Subject: [PATCH 3/5] More terse docstring. --- Doc/library/itertools.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 87179ecfb38c73..1c4d5b42714fa2 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -883,7 +883,7 @@ and :term:`generators ` which incur interpreter overhead. return iter(collections.deque(iterable, maxlen=n)) def loops(n): - "Loop n times. Like range(n) but faster because no integers are produced." + "Loop n times. Like range(n) but without creating integers." # for _ in loops(100): ... return repeat(None, n) From 62200aa933348e40ca44e6f763cda239d01d3b06 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 30 Nov 2024 12:28:23 -0600 Subject: [PATCH 4/5] Move loops() before tail() --- Doc/library/itertools.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 1c4d5b42714fa2..e10d0ccec0660d 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -877,16 +877,16 @@ and :term:`generators ` which incur interpreter overhead. "Returns the sequence elements n times." return chain.from_iterable(repeat(tuple(iterable), n)) - def tail(n, iterable): - "Return an iterator over the last n items." - # tail(3, 'ABCDEFG') → E F G - return iter(collections.deque(iterable, maxlen=n)) - def loops(n): "Loop n times. Like range(n) but without creating integers." # for _ in loops(100): ... return repeat(None, n) + def tail(n, iterable): + "Return an iterator over the last n items." + # tail(3, 'ABCDEFG') → E F G + return iter(collections.deque(iterable, maxlen=n)) + def consume(iterator, n=None): "Advance the iterator n-steps ahead. If n is None, consume entirely." # Use functions that consume iterators at C speed. @@ -1212,15 +1212,6 @@ The following recipes have a more mathematical flavor: [0, 2, 4, 6] - >>> list(tail(3, 'ABCDEFG')) - ['E', 'F', 'G'] - >>> # Verify the input is consumed greedily - >>> input_iterator = iter('ABCDEFG') - >>> output_iterator = tail(3, input_iterator) - >>> list(input_iterator) - [] - - >>> for _ in loops(5): ... print('hi') ... @@ -1231,6 +1222,15 @@ The following recipes have a more mathematical flavor: hi + >>> list(tail(3, 'ABCDEFG')) + ['E', 'F', 'G'] + >>> # Verify the input is consumed greedily + >>> input_iterator = iter('ABCDEFG') + >>> output_iterator = tail(3, input_iterator) + >>> list(input_iterator) + [] + + >>> it = iter(range(10)) >>> consume(it, 3) >>> # Verify the input is consumed lazily From ad10fd62b63c1553a90e682b36156ffe25204b96 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 2 Dec 2024 09:09:22 -0600 Subject: [PATCH 5/5] Add comment to tests --- Doc/library/itertools.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index e10d0ccec0660d..03966f3d3d694b 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -1501,6 +1501,7 @@ The following recipes have a more mathematical flavor: >>> carmichael = {561, 1105, 1729, 2465, 2821, 6601, 8911} # https://oeis.org/A002997 >>> any(map(is_prime, carmichael)) False + >>> # https://www.wolframalpha.com/input?i=is+128884753939+prime >>> is_prime(128_884_753_939) # large prime True >>> is_prime(999953 * 999983) # large semiprime