@@ -134,7 +134,7 @@ loops that truncate the stream.
134134 total = func(total, element)
135135 yield total
136136
137- There are a number of uses for the *func * argument. It can be set to
137+ The *func * argument can be set to
138138 :func: `min ` for a running minimum, :func: `max ` for a running maximum, or
139139 :func: `operator.mul ` for a running product. Amortization tables can be
140140 built by accumulating interest and applying payments:
@@ -181,21 +181,16 @@ loops that truncate the stream.
181181 >>> unflattened
182182 [('roses', 'red'), ('violets', 'blue'), ('sugar', 'sweet')]
183183
184- >>> for batch in batched(' ABCDEFG' , 3 ):
185- ... print (batch)
186- ...
187- ('A', 'B', 'C')
188- ('D', 'E', 'F')
189- ('G',)
190-
191184 Roughly equivalent to::
192185
193186 def batched(iterable, n):
194187 # batched('ABCDEFG', 3) → ABC DEF G
195188 if n < 1:
196189 raise ValueError('n must be at least one')
197- it = iter(iterable)
198- while batch := tuple(islice(it, n)):
190+ iterable = iter(iterable)
191+ while batch := tuple(islice(iterable, n)):
192+ if strict and len(batch) != n:
193+ raise ValueError('batched(): incomplete batch')
199194 yield batch
200195
201196 .. versionadded :: 3.12
@@ -229,13 +224,13 @@ loops that truncate the stream.
229224
230225 Return *r * length subsequences of elements from the input *iterable *.
231226
232- The combination tuples are emitted in lexicographic ordering according to
227+ The combination tuples are emitted in lexicographic order according to
233228 the order of the input *iterable *. So, if the input *iterable * is sorted,
234229 the output tuples will be produced in sorted order.
235230
236231 Elements are treated as unique based on their position, not on their
237- value. So if the input elements are unique, there will be no repeated
238- values in each combination.
232+ value. So, if the input elements are unique, there will be no repeated
233+ values within each combination.
239234
240235 Roughly equivalent to::
241236
@@ -278,12 +273,12 @@ loops that truncate the stream.
278273 Return *r * length subsequences of elements from the input *iterable *
279274 allowing individual elements to be repeated more than once.
280275
281- The combination tuples are emitted in lexicographic ordering according to
276+ The combination tuples are emitted in lexicographic order according to
282277 the order of the input *iterable *. So, if the input *iterable * is sorted,
283278 the output tuples will be produced in sorted order.
284279
285280 Elements are treated as unique based on their position, not on their
286- value. So if the input elements are unique, the generated combinations
281+ value. So, if the input elements are unique, the generated combinations
287282 will also be unique.
288283
289284 Roughly equivalent to::
@@ -324,13 +319,13 @@ loops that truncate the stream.
324319.. function :: compress(data, selectors)
325320
326321 Make an iterator that filters elements from *data * returning only those that
327- have a corresponding element in *selectors * that evaluates to `` True `` .
328- Stops when either the *data * or *selectors * iterables has been exhausted.
322+ have a corresponding element in *selectors * is true .
323+ Stops when either the *data * or *selectors * iterables have been exhausted.
329324 Roughly equivalent to::
330325
331326 def compress(data, selectors):
332327 # compress('ABCDEF', [1,0,1,0,1,1]) → A C E F
333- return (d for d, s in zip(data, selectors) if s )
328+ return (datum for datum, selector in zip(data, selectors) if selector )
334329
335330 .. versionadded :: 3.1
336331
@@ -384,7 +379,7 @@ loops that truncate the stream.
384379 start-up time. Roughly equivalent to::
385380
386381 def dropwhile(predicate, iterable):
387- # dropwhile(lambda x: x<5, [1,4,6,4,1 ]) → 6 4 1
382+ # dropwhile(lambda x: x<5, [1,4,6,3,8 ]) → 6 3 8
388383 iterable = iter(iterable)
389384 for x in iterable:
390385 if not predicate(x):
@@ -400,7 +395,7 @@ loops that truncate the stream.
400395 that are false. Roughly equivalent to::
401396
402397 def filterfalse(predicate, iterable):
403- # filterfalse(lambda x: x%2, range(10)) → 0 2 4 6 8
398+ # filterfalse(lambda x: x<5, [1,4,6,3,8]) → 6 8
404399 if predicate is None:
405400 predicate = bool
406401 for x in iterable:
@@ -436,36 +431,37 @@ loops that truncate the stream.
436431
437432 :func: `groupby ` is roughly equivalent to::
438433
439- class groupby:
434+ def groupby(iterable, key=None) :
440435 # [k for k, g in groupby('AAAABBBCCDAABBB')] → A B C D A B
441436 # [list(g) for k, g in groupby('AAAABBBCCD')] → AAAA BBB CC D
442437
443- def __init__(self, iterable, key=None):
444- if key is None:
445- key = lambda x: x
446- self.keyfunc = key
447- self.it = iter(iterable)
448- self.tgtkey = self.currkey = self.currvalue = object()
449-
450- def __iter__(self):
451- return self
452-
453- def __next__(self):
454- self.id = object()
455- while self.currkey == self.tgtkey:
456- self.currvalue = next(self.it) # Exit on StopIteration
457- self.currkey = self.keyfunc(self.currvalue)
458- self.tgtkey = self.currkey
459- return (self.currkey, self._grouper(self.tgtkey, self.id))
460-
461- def _grouper(self, tgtkey, id):
462- while self.id is id and self.currkey == tgtkey:
463- yield self.currvalue
464- try:
465- self.currvalue = next(self.it)
466- except StopIteration:
438+ keyfunc = (lambda x: x) if key is None else key
439+ iterator = iter(iterable)
440+ exhausted = False
441+
442+ def _grouper(target_key):
443+ nonlocal curr_value, curr_key, exhausted
444+ yield curr_value
445+ for curr_value in iterator:
446+ curr_key = keyfunc(curr_value)
447+ if curr_key != target_key:
467448 return
468- self.currkey = self.keyfunc(self.currvalue)
449+ yield curr_value
450+ exhausted = True
451+
452+ try:
453+ curr_value = next(iterator)
454+ except StopIteration:
455+ return
456+ curr_key = keyfunc(curr_value)
457+
458+ while not exhausted:
459+ target_key = curr_key
460+ curr_group = _grouper(target_key)
461+ yield curr_key, curr_group
462+ if curr_key == target_key:
463+ for _ in curr_group:
464+ pass
469465
470466
471467.. function :: islice(iterable, stop)
@@ -493,13 +489,15 @@ loops that truncate the stream.
493489 # islice('ABCDEFG', 2, 4) → C D
494490 # islice('ABCDEFG', 2, None) → C D E F G
495491 # islice('ABCDEFG', 0, None, 2) → A C E G
492+
496493 s = slice(*args)
497494 start = 0 if s.start is None else s.start
498495 stop = s.stop
499496 step = 1 if s.step is None else s.step
500497 if start < 0 or (stop is not None and stop < 0) or step <= 0:
501498 raise ValueError
502- indices = count() if stop is None else range(max(stop, start))
499+
500+ indices = count() if stop is None else range(max(start, stop))
503501 next_i = start
504502 for i, element in zip(indices, iterable):
505503 if i == next_i:
@@ -541,22 +539,25 @@ loops that truncate the stream.
541539 the output tuples will be produced in sorted order.
542540
543541 Elements are treated as unique based on their position, not on their
544- value. So if the input elements are unique, there will be no repeated
542+ value. So, if the input elements are unique, there will be no repeated
545543 values within a permutation.
546544
547545 Roughly equivalent to::
548546
549547 def permutations(iterable, r=None):
550548 # permutations('ABCD', 2) → AB AC AD BA BC BD CA CB CD DA DB DC
551549 # permutations(range(3)) → 012 021 102 120 201 210
550+
552551 pool = tuple(iterable)
553552 n = len(pool)
554553 r = n if r is None else r
555554 if r > n:
556555 return
556+
557557 indices = list(range(n))
558558 cycles = list(range(n, n-r, -1))
559559 yield tuple(pool[i] for i in indices[:r])
560+
560561 while n:
561562 for i in reversed(range(r)):
562563 cycles[i] -= 1
@@ -572,7 +573,7 @@ loops that truncate the stream.
572573 return
573574
574575 The code for :func: `permutations ` can be also expressed as a subsequence of
575- :func: `product `, filtered to exclude entries with repeated elements (those
576+ :func: `product ` filtered to exclude entries with repeated elements (those
576577 from the same position in the input pool)::
577578
578579 def permutations(iterable, r=None):
@@ -666,17 +667,16 @@ loops that truncate the stream.
666667 predicate is true. Roughly equivalent to::
667668
668669 def takewhile(predicate, iterable):
669- # takewhile(lambda x: x<5, [1,4,6,4,1 ]) → 1 4
670+ # takewhile(lambda x: x<5, [1,4,6,3,8 ]) → 1 4
670671 for x in iterable:
671- if predicate(x):
672- yield x
673- else:
672+ if not predicate(x):
674673 break
674+ yield x
675675
676676 Note, the element that first fails the predicate condition is
677677 consumed from the input iterator and there is no way to access it.
678678 This could be an issue if an application wants to further consume the
679- input iterator after takewhile has been run to exhaustion. To work
679+ input iterator after * takewhile * has been run to exhaustion. To work
680680 around this problem, consider using `more-iterools before_and_after()
681681 <https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.before_and_after> `_
682682 instead.
@@ -726,10 +726,12 @@ loops that truncate the stream.
726726
727727 def zip_longest(*iterables, fillvalue=None):
728728 # zip_longest('ABCD', 'xy', fillvalue='-') → Ax By C- D-
729- iterators = [iter(it) for it in iterables]
729+
730+ iterators = list(map(iter, iterables))
730731 num_active = len(iterators)
731732 if not num_active:
732733 return
734+
733735 while True:
734736 values = []
735737 for i, iterator in enumerate(iterators):
0 commit comments