@@ -122,15 +122,15 @@ loops that truncate the stream.
122122 # accumulate([1,2,3,4,5]) → 1 3 6 10 15
123123 # accumulate([1,2,3,4,5], initial=100) → 100 101 103 106 110 115
124124 # accumulate([1,2,3,4,5], operator.mul) → 1 2 6 24 120
125- it = iter(iterable)
125+ iterator = iter(iterable)
126126 total = initial
127127 if initial is None:
128128 try:
129- total = next(it )
129+ total = next(iterator )
130130 except StopIteration:
131131 return
132132 yield total
133- for element in it :
133+ for element in iterator :
134134 total = func(total, element)
135135 yield total
136136
@@ -218,9 +218,8 @@ loops that truncate the stream.
218218
219219 def chain(*iterables):
220220 # chain('ABC', 'DEF') → A B C D E F
221- for it in iterables:
222- for element in it:
223- yield element
221+ for iterable in iterables:
222+ yield from iterable
224223
225224
226225.. classmethod :: chain.from_iterable(iterable)
@@ -230,9 +229,8 @@ loops that truncate the stream.
230229
231230 def from_iterable(iterables):
232231 # chain.from_iterable(['ABC', 'DEF']) → A B C D E F
233- for it in iterables:
234- for element in it:
235- yield element
232+ for iterable in iterables:
233+ yield from iterable
236234
237235
238236.. function :: combinations(iterable, r)
@@ -380,7 +378,7 @@ loops that truncate the stream.
380378 saved.append(element)
381379 while saved:
382380 for element in saved:
383- yield element
381+ yield element
384382
385383 Note, this member of the toolkit may require significant auxiliary storage
386384 (depending on the length of the iterable).
@@ -615,10 +613,10 @@ loops that truncate the stream.
615613 This function is roughly equivalent to the following code, except that the
616614 actual implementation does not build up intermediate results in memory::
617615
618- def product(*args , repeat=1):
616+ def product(*iterables , repeat=1):
619617 # product('ABCD', 'xy') → Ax Ay Bx By Cx Cy Dx Dy
620618 # product(range(2), repeat=3) → 000 001 010 011 100 101 110 111
621- pools = [tuple(pool) for pool in args ] * repeat
619+ pools = [tuple(pool) for pool in iterables ] * repeat
622620 result = [[]]
623621 for pool in pools:
624622 result = [x+[y] for x in result for y in pool]
@@ -696,24 +694,23 @@ loops that truncate the stream.
696694
697695 Return *n * independent iterators from a single iterable.
698696
699- The following Python code helps explain what *tee * does (although the actual
700- implementation is more complex and uses only a single underlying
701- :abbr: `FIFO ( first-in, first-out ) ` queue)::
697+ Roughly equivalent to::
702698
703699 def tee(iterable, n=2):
704- it = iter(iterable)
705- deques = [collections.deque() for i in range(n)]
706- def gen(mydeque):
700+ iterator = iter(iterable)
701+ shared_link = [None, None]
702+ return tuple(_tee(iterator, shared_link) for _ in range(n))
703+
704+ def _tee(iterator, link):
705+ try:
707706 while True:
708- if not mydeque: # when the local deque is empty
709- try:
710- newval = next(it) # fetch a new value and
711- except StopIteration:
712- return
713- for d in deques: # load it to all the deques
714- d.append(newval)
715- yield mydeque.popleft()
716- return tuple(gen(d) for d in deques)
707+ if link[1] is None:
708+ link[0] = next(iterator)
709+ link[1] = [None, None]
710+ value, link = link
711+ yield value
712+ except StopIteration:
713+ return
717714
718715 Once a :func: `tee ` has been created, the original *iterable * should not be
719716 used anywhere else; otherwise, the *iterable * could get advanced without
@@ -735,17 +732,17 @@ loops that truncate the stream.
735732 iterables are of uneven length, missing values are filled-in with *fillvalue *.
736733 Iteration continues until the longest iterable is exhausted. Roughly equivalent to::
737734
738- def zip_longest(*args , fillvalue=None):
735+ def zip_longest(*iterables , fillvalue=None):
739736 # zip_longest('ABCD', 'xy', fillvalue='-') → Ax By C- D-
740- iterators = [iter(it) for it in args ]
737+ iterators = [iter(it) for it in iterables ]
741738 num_active = len(iterators)
742739 if not num_active:
743740 return
744741 while True:
745742 values = []
746- for i, it in enumerate(iterators):
743+ for i, iterator in enumerate(iterators):
747744 try:
748- value = next(it )
745+ value = next(iterator )
749746 except StopIteration:
750747 num_active -= 1
751748 if not num_active:
@@ -800,6 +797,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
800797.. testcode ::
801798
802799 import collections
800+ import contextlib
803801 import functools
804802 import math
805803 import operator
@@ -942,32 +940,26 @@ and :term:`generators <generator>` which incur interpreter overhead.
942940 # iter_index('AABCADEAF', 'A') → 0 1 4 7
943941 seq_index = getattr(iterable, 'index', None)
944942 if seq_index is None:
945- # Path for general iterables
946943 iterator = islice(iterable, start, stop)
947944 for i, element in enumerate(iterator, start):
948945 if element is value or element == value:
949946 yield i
950947 else:
951- # Path for sequences with an index() method
952948 stop = len(iterable) if stop is None else stop
953949 i = start
954- try :
950+ with contextlib.suppress(ValueError) :
955951 while True:
956952 yield (i := seq_index(value, i, stop))
957953 i += 1
958- except ValueError:
959- pass
960954
961955 def iter_except(func, exception, first=None):
962956 "Convert a call-until-exception interface to an iterator interface."
963957 # iter_except(d.popitem, KeyError) → non-blocking dictionary iterator
964- try :
958+ with contextlib.suppress(exception) :
965959 if first is not None:
966960 yield first()
967961 while True:
968962 yield func()
969- except exception:
970- pass
971963
972964
973965The following recipes have a more mathematical flavor:
0 commit comments