@@ -865,26 +865,22 @@ which incur interpreter overhead.
865865 # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
866866 return next(filter(pred, iterable), default)
867867
868- def iter_index(iterable, value, start=0):
868+ def iter_index(iterable, value, start=0, stop=None ):
869869 "Return indices where a value occurs in a sequence or iterable."
870870 # iter_index('AABCADEAF', 'A') --> 0 1 4 7
871- try:
872- seq_index = iterable.index
873- except AttributeError:
871+ seq_index = getattr(iterable, 'index', None)
872+ if seq_index is None:
874873 # Slow path for general iterables
875- it = islice(iterable, start, None)
876- i = start - 1
877- try:
878- while True:
879- yield (i := i + operator.indexOf(it, value) + 1)
880- except ValueError:
881- pass
874+ it = islice(iterable, start, stop)
875+ for i, element in enumerate(it, start):
876+ if element is value or element == value:
877+ yield i
882878 else:
883879 # Fast path for sequences
884880 i = start - 1
885881 try:
886882 while True:
887- yield (i := seq_index(value, i+1))
883+ yield (i := seq_index(value, i+1, stop ))
888884 except ValueError:
889885 pass
890886
@@ -1331,6 +1327,21 @@ The following recipes have a more mathematical flavor:
13311327 []
13321328 >>> list (iter_index(iter (' AABCADEAF' ), ' A' , 10 ))
13331329 []
1330+ >>> list (iter_index(' AABCADEAF' , ' A' , 1 , 7 ))
1331+ [1, 4]
1332+ >>> list (iter_index(iter (' AABCADEAF' ), ' A' , 1 , 7 ))
1333+ [1, 4]
1334+ >>> # Verify that ValueErrors not swallowed (gh-107208)
1335+ >>> def assert_no_value (iterable , forbidden_value ):
1336+ ... for item in iterable:
1337+ ... if item == forbidden_value:
1338+ ... raise ValueError
1339+ ... yield item
1340+ ...
1341+ >>> list (iter_index(assert_no_value(' AABCADEAF' , ' B' ), ' A' ))
1342+ Traceback (most recent call last):
1343+ ...
1344+ ValueError
13341345
13351346 >>> list (sieve(30 ))
13361347 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
0 commit comments