Author terry.reedy
Recipients cool-RR, josh.r, rhettinger, terry.reedy
Date 2014-07-15.21:37:03
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1405460223.37.0.00134256260724.issue20663@psf.upfronthosting.co.za>
In-reply-to
Content
Here is a test that now fails.
------------
from collections import deque

d = deque((0,))
old = []
try:
    while True:
        n = d.popleft()
        old.append((n, len(d)))
        if n < 5:
            d.extend((n+1, n+2))
except IndexError:
    pass

d = deque((0,))
new = []
for n in iter(d.popleft, exception=IndexError):
        new.append((n, len(d)))
        if n < 5:
            d.extend((n+1, n+2))

assert new == old
--------

Here is Python code, partly from my python-ideas comments, that makes the test pass. This version allows stopping on both a sentinel value and an exception (or tuple thereof, I believe).
-------
__sentinel = object()

class callable_iterator:
    class stop_exception: pass

    def __init__(self, func, sentinel, exception):
        self.func = func
        self.sentinel = sentinel
        if exception is not None:
            self.stop_exception = exception
    def __iter__(self):
        return self
    def __next__(self):
        try:
            x = self.func()
        except self.stop_exception:
            raise StopIteration from None
        if x == self.sentinel:
            raise StopIteration
        else:
            return x

def iter(it_func, sentinel=__sentinel, exception=None):
    if sentinel == __sentinel and exception == None:
        pass  # do as at present
    else:
        return callable_iterator(it_func, sentinel, exception)
History
Date User Action Args
2014-07-15 21:37:03terry.reedysetrecipients: + terry.reedy, rhettinger, cool-RR, josh.r
2014-07-15 21:37:03terry.reedysetmessageid: <1405460223.37.0.00134256260724.issue20663@psf.upfronthosting.co.za>
2014-07-15 21:37:03terry.reedylinkissue20663 messages
2014-07-15 21:37:03terry.reedycreate