r79486 - python/branches/release30-maint/Doc/library/itertools.rst
![](https://secure.gravatar.com/avatar/8ac615df352a970211b0e3d94a307c6d.jpg?s=120&d=mm&r=g)
Author: raymond.hettinger Date: Sun Mar 28 20:32:17 2010 New Revision: 79486 Log: Update itertools recipes. Modified: python/branches/release30-maint/Doc/library/itertools.rst Modified: python/branches/release30-maint/Doc/library/itertools.rst ============================================================================== --- python/branches/release30-maint/Doc/library/itertools.rst (original) +++ python/branches/release30-maint/Doc/library/itertools.rst Sun Mar 28 20:32:17 2010 @@ -510,16 +510,19 @@ "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" @@ -611,10 +614,9 @@ 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) @@ -627,3 +629,33 @@ # 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))
![](https://secure.gravatar.com/avatar/003518259e6453b071aeaa7f6e6ed37b.jpg?s=120&d=mm&r=g)
On 28/03/2010 21.32, raymond.hettinger wrote:
Author: raymond.hettinger Date: Sun Mar 28 20:32:17 2010 New Revision: 79486
Log: Update itertools recipes.
Modified: python/branches/release30-maint/Doc/library/itertools.rst
[...]
Hi, release30-maint is not maintained anymore, and the 3.0 docs have a warning with a link to the 3.1 doc (http://docs.python.org/dev/3.0/library/itertools.html) so there's no need to updated it. Also you should use "svnmerge.py merge -r xxxxx" to merge commits, committing first on trunk, then using svnmerge to port to release26-maint and py3k and finally to backport the py3k commit to release31-maint. Best Regards, Ezio Melotti
![](https://secure.gravatar.com/avatar/f3ba3ecffd20251d73749afbfa636786.jpg?s=120&d=mm&r=g)
Ezio Melotti wrote:
Also you should use "svnmerge.py merge -r xxxxx" to merge commits, committing first on trunk, then using svnmerge to port to release26-maint and py3k and finally to backport the py3k commit to release31-maint.
Raymond's not using svnmerge is a historical quirk from when svnmerge was first introduced as an optional tool to help manage the repository. To gain acceptance of the new tool, it was made clear that existing committers could keep doing what they were used to doing (i.e. manual backports and forward ports) and those pushing for the adoption of svnmerge would take care of recording the fact that those merges had happened. That exception is actually still in effect, it's just that a lot of us have switched to using svnmerge anyway. Since we also tell any new committers to use it, we tend not to advertise the existence of the "legacy workflow" clause all that much :) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
participants (3)
-
Ezio Melotti
-
Nick Coghlan
-
raymond.hettinger