diff options
author | Raymond Hettinger <python@rcn.com> | 2010-03-28 18:27:13 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2010-03-28 18:27:13 (GMT) |
commit | fc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0 (patch) | |
tree | 30e0d780cd2cbd0b7f8c24f9938d648df2a03561 /Doc/library/itertools.rst | |
parent | fd1b0930ce6a84096d30c03a70cd9e0ee4a3178f (diff) | |
download | cpython-fc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0.zip cpython-fc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0.tar.gz cpython-fc91aa28fd8dad5280fd4d3a4747b5e08ee37ac0.tar.bz2 |
Update itertools recipes.
Diffstat (limited to 'Doc/library/itertools.rst')
-rw-r--r-- | Doc/library/itertools.rst | 48 |
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)) |