]> granicus.if.org Git - python/commitdiff
Generalize the itertools.tee() recipe.
authorRaymond Hettinger <python@rcn.com>
Wed, 18 Feb 2009 20:56:51 +0000 (20:56 +0000)
committerRaymond Hettinger <python@rcn.com>
Wed, 18 Feb 2009 20:56:51 +0000 (20:56 +0000)
Doc/library/itertools.rst

index 7fdadd2aa0a3c445717af42b0488e62133dfb525..491cb184a18200dc0cc912b9f66d3d1dd8e23141 100644 (file)
@@ -130,7 +130,7 @@ loops that truncate the stream.
                 return
             indices = list(range(r))
             yield tuple(pool[i] for i in indices)
-            while 1:
+            while True:
                 for i in reversed(range(r)):
                     if indices[i] != i + n - r:
                         break
@@ -178,7 +178,7 @@ loops that truncate the stream.
                 return
             indices = [0] * r
             yield tuple(pool[i] for i in indices)
-            while 1:
+            while True:
                 for i in reversed(range(r)):
                     if indices[i] != n - 1:
                         break
@@ -501,28 +501,28 @@ loops that truncate the stream.
 
 .. function:: tee(iterable[, n=2])
 
-   Return *n* independent iterators from a single iterable. The case where ``n==2``
-   is equivalent to::
-
-      def tee(iterable):
-          def gen(next, data={}):
-              for i in count():
-                  if i in data:
-                      yield data.pop(i)
-                  else:
-                      data[i] = next()
-                      yield data[i]
-          it = iter(iterable)
-          return (gen(it.__next__), gen(it.__next__))
-
-   Note, once :func:`tee` has made a split, the original *iterable* should not be
-   used anywhere else; otherwise, the *iterable* could get advanced without the tee
-   objects being informed.
-
-   Note, this member of the toolkit may require significant auxiliary storage
-   (depending on how much temporary data needs to be stored). In general, if one
-   iterator is going to use most or all of the data before the other iterator, it
-   is faster to use :func:`list` instead of :func:`tee`.
+   Return *n* independent iterators from a single iterable.  Equivalent to::
+
+        def tee(iterable, n=2):
+            it = iter(iterable)
+            deques = [collections.deque() for i in range(n)]
+            def gen(mydeque):
+                while True:
+                    if not mydeque:             # when the local deque is empty
+                        newval = next(it)       # fetch a new value and
+                        for d in deques:        # load it to all the deques
+                            d.append(newval)
+                    yield mydeque.popleft()
+            return tuple(gen(d) for d in deques)
+
+   Once :func:`tee` has made a split, the original *iterable* should not be
+   used anywhere else; otherwise, the *iterable* could get advanced without
+   the tee objects being informed.
+
+   This itertool may require significant auxiliary storage (depending on how
+   much temporary data needs to be stored). In general, if one iterator uses
+   most or all of the data before another iterator starts, it is faster to use
+   :func:`list` instead of :func:`tee`.
 
 
 .. function:: zip_longest(*iterables[, fillvalue])