summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2023-09-03 03:25:13 (GMT)
committerGitHub <noreply@github.com>2023-09-03 03:25:13 (GMT)
commitf373c6b9483e12d7f6e03a631601149ed60ab883 (patch)
tree300f9d95a6805b5d65046ae5be11edfc7517eee8
parenta52213bf830226fd969dc2a2ef8006c89edecc35 (diff)
downloadcpython-f373c6b9483e12d7f6e03a631601149ed60ab883.zip
cpython-f373c6b9483e12d7f6e03a631601149ed60ab883.tar.gz
cpython-f373c6b9483e12d7f6e03a631601149ed60ab883.tar.bz2
gh-107208: Fix iter_index() recipe to not swallow exceptions (gh-108835)
gh-107208: iter_index now supports "stop" and no longer swallows ValueError
-rw-r--r--Doc/library/itertools.rst35
1 files changed, 23 insertions, 12 deletions
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index d0bb469..4224371 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -865,26 +865,22 @@ which incur interpreter overhead.
# first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
return next(filter(pred, iterable), default)
- def iter_index(iterable, value, start=0):
+ def iter_index(iterable, value, start=0, stop=None):
"Return indices where a value occurs in a sequence or iterable."
# iter_index('AABCADEAF', 'A') --> 0 1 4 7
- try:
- seq_index = iterable.index
- except AttributeError:
+ seq_index = getattr(iterable, 'index', None)
+ if seq_index is None:
# Slow path for general iterables
- it = islice(iterable, start, None)
- i = start - 1
- try:
- while True:
- yield (i := i + operator.indexOf(it, value) + 1)
- except ValueError:
- pass
+ it = islice(iterable, start, stop)
+ for i, element in enumerate(it, start):
+ if element is value or element == value:
+ yield i
else:
# Fast path for sequences
i = start - 1
try:
while True:
- yield (i := seq_index(value, i+1))
+ yield (i := seq_index(value, i+1, stop))
except ValueError:
pass
@@ -1331,6 +1327,21 @@ The following recipes have a more mathematical flavor:
[]
>>> list(iter_index(iter('AABCADEAF'), 'A', 10))
[]
+ >>> list(iter_index('AABCADEAF', 'A', 1, 7))
+ [1, 4]
+ >>> list(iter_index(iter('AABCADEAF'), 'A', 1, 7))
+ [1, 4]
+ >>> # Verify that ValueErrors not swallowed (gh-107208)
+ >>> def assert_no_value(iterable, forbidden_value):
+ ... for item in iterable:
+ ... if item == forbidden_value:
+ ... raise ValueError
+ ... yield item
+ ...
+ >>> list(iter_index(assert_no_value('AABCADEAF', 'B'), 'A'))
+ Traceback (most recent call last):
+ ...
+ ValueError
>>> list(sieve(30))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]