diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-09-04 11:46:35 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-04 11:46:35 (GMT) |
commit | 183bb673a8ce65d6bef6c8da44f34ba70f25340b (patch) | |
tree | 68bdf12c794b2bad9b2d08ff4af7c2c4e1b579cd | |
parent | c8cf6be213826c8d0e3e2acbcf31b8c1069df3ed (diff) | |
download | cpython-183bb673a8ce65d6bef6c8da44f34ba70f25340b.zip cpython-183bb673a8ce65d6bef6c8da44f34ba70f25340b.tar.gz cpython-183bb673a8ce65d6bef6c8da44f34ba70f25340b.tar.bz2 |
[3.12] gh-107208: Fix iter_index() recipe to not swallow exceptions (gh-108835) (#108837)
gh-107208: Fix iter_index() recipe to not swallow exceptions (gh-108835)
(cherry picked from commit f373c6b9483e12d7f6e03a631601149ed60ab883)
gh-107208: iter_index now supports "stop" and no longer swallows ValueError
Co-authored-by: Raymond Hettinger <rhettinger@users.noreply.github.com>
-rw-r--r-- | Doc/library/itertools.rst | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 730736b..72c6851 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 @@ -1333,6 +1329,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] |