summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2010-03-28 18:27:13 (GMT)
committerRaymond Hettinger <python@rcn.com>2010-03-28 18:27:13 (GMT)
commitfc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0 (patch)
tree30e0d780cd2cbd0b7f8c24f9938d648df2a03561
parentfd1b0930ce6a84096d30c03a70cd9e0ee4a3178f (diff)
downloadcpython-fc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0.zip
cpython-fc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0.tar.gz
cpython-fc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0.tar.bz2
Update itertools recipes.
-rw-r--r--Doc/library/itertools.rst48
1 files changed, 40 insertions, 8 deletions
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index 5eb5806..84f4231 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -580,16 +580,19 @@ which incur interpreter overhead.
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
- def enumerate(iterable, start=0):
- return zip(count(start), iterable)
-
def tabulate(function, start=0):
"Return function(0), function(1), ..."
return map(function, count(start))
def consume(iterator, n):
"Advance the iterator n-steps ahead. If n is none, consume entirely."
- collections.deque(islice(iterator, n), maxlen=0)
+ # Use functions that consume iterators at C speed.
+ if n is None:
+ # feed the entire iterator into a zero-length deque
+ collections.deque(iterator, maxlen=0)
+ else:
+ # advance to the emtpy slice starting at position n
+ next(islice(iterator, n, n), None)
def nth(iterable, n, default=None):
"Returns the nth item or a default value"
@@ -661,10 +664,9 @@ which incur interpreter overhead.
seen = set()
seen_add = seen.add
if key is None:
- for element in iterable:
- if element not in seen:
- seen_add(element)
- yield element
+ for element in filterfalse(seen.__contains__, iterable):
+ seen_add(element)
+ yield element
else:
for element in iterable:
k = key(element)
@@ -677,3 +679,33 @@ which incur interpreter overhead.
# unique_justseen('AAAABBBCCDAABBB') --> A B C D A B
# unique_justseen('ABBCcAD', str.lower) --> A B C A D
return map(next, map(itemgetter(1), groupby(iterable, key)))
+
+ def iter_except(func, exception, first=None):
+ """ Call a function repeatedly until an exception is raised.
+
+ Converts a call-until-exception interface to an iterator interface.
+ Like __builtin__.iter(func, sentinel) but uses an exception instead
+ of a sentinel to end the loop.
+
+ Examples:
+ iter_except(functools.partial(heappop, h), IndexError) # priority queue iterator
+ iter_except(d.popitem, KeyError) # non-blocking dict iterator
+ iter_except(d.popleft, IndexError) # non-blocking deque iterator
+ iter_except(q.get_nowait, Queue.Empty) # loop over a producer Queue
+ iter_except(s.pop, KeyError) # non-blocking set iterator
+
+ """
+ try:
+ if first is not None:
+ yield first() # For database APIs needing an initial cast to db.first()
+ while 1:
+ yield func()
+ except exception:
+ pass
+
+Note, many of the above recipes can be optimized by replacing global lookups
+with local variables defined as default values. For example, the
+*dotproduct* recipe can be written as::
+
+ def dotproduct(vec1, vec2, sum=sum, map=map, mul=operator.mul):
+ return sum(map(mul, vec1, vec2))