@@ -865,26 +865,22 @@ which incur interpreter overhead.
865
865
# first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
866
866
return next(filter(pred, iterable), default)
867
867
868
- def iter_index(iterable, value, start=0):
868
+ def iter_index(iterable, value, start=0, stop=None ):
869
869
"Return indices where a value occurs in a sequence or iterable."
870
870
# 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:
874
873
# 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
882
878
else:
883
879
# Fast path for sequences
884
880
i = start - 1
885
881
try:
886
882
while True:
887
- yield (i := seq_index(value, i+1))
883
+ yield (i := seq_index(value, i+1, stop ))
888
884
except ValueError:
889
885
pass
890
886
@@ -1331,6 +1327,21 @@ The following recipes have a more mathematical flavor:
1331
1327
[]
1332
1328
>>> list (iter_index(iter (' AABCADEAF' ), ' A' , 10 ))
1333
1329
[]
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
1334
1345
1335
1346
>>> list (sieve(30 ))
1336
1347
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
0 commit comments